Как отфильтровать выходные столбцы с помощью WCF OData Services? - PullRequest
1 голос
/ 30 марта 2012

Для заданного набора сущностей, скажем WHO_TYPES, я хочу ограничить столбцы ID и WHO_TYPE_NAME.

Набор сущностей сам выставляется через:

config.SetEntitySetAccessRule("WHO_TYPES", EntitySetRights.AllRead);

... поэтому я не вижу, как это сделать при настройке правил доступа к сущности / таблице. Можно ли написать QueryInterceptor для достижения этой цели? Если да, то как?

Другая попытка, которую я сделал, - написать собственный метод, который ссылается на пользовательский объект:

[DataServiceKey("MY_WHO_TYPES")]
public partial class MY_WHO_TYPES
{
    public MY_WHO_TYPES() { }

    public int MY_WID { get; set; }
    public string MY_WNAME { get; set; }
}

Мой пользовательский метод:

    [WebGet]
    public IQueryable<MY_WHO_TYPES> GetWhoTypesCustom()
    {
        var whoCustom = from w in this.CurrentDataSource.WHO_TYPES
                        select new MY_WHO_TYPES() { MY_WID = w.ID, MY_WNAME = w.WHO_TYPE_NAME };

        return whoCustom.AsQueryable<MY_WHO_TYPES>();
    }

При этой попытке я получаю следующее сообщение об ошибке:

Unable to load metadata for return type 'System.Linq.IQueryable`1[DAL.Models.MY_WHO_TYPES]' of method 'System.Linq.IQueryable`1[DAL.Models.MY_WHO_TYPES] GetWhoTypesCustom()'.

Я чувствую какой-то шаблон хранилища, появляющийся в ответе, но я надеюсь, что это может быть проще.

Предложение об использовании Tuple звучит хорошо, но я не совсем уверен, как его реализовать или какой будет тип возвращаемого значения:

select new { Tuple<int, string> (w.ID, w.WHO_TYPE_NAME)};  // error: Invalid anonymous type member declarator.  Anonymous type members must be declared with a memeber assignment...

Затем я попытался просто вернуть анонимный тип:

    [WebGet]
    public IQueryable GetWhoTypesCustom()
    {
        var whoCustom = from w in this.CurrentDataSource.WHO_TYPES
                        select new { w.ID, w.WHO_TYPE_NAME };
        return whoCustom;
    }

Проблема в том, что я получаю сообщение об ошибке, указывающее, что тип IQueryable не определен.

1 Ответ

1 голос
/ 03 апреля 2012

Самый простой способ сделать это - использовать хранимые процедуры вместо самих сущностей.

Это включает создание сложного типа из sproc. Определите столбцы, которые вы хотите вернуть в sproc, и создайте сложный объект при создании ваших сущностей.

В представлении * .edmx:

Right-click / Add / Function Import
Select the sproc
Give it a Function Import Name
Click Get Column Information
Click Create New Complex Type - give it a name (by default looks like [Function Import Name]_Result

То, что должно работать, но, похоже, существует некоторая проблема при использовании службы, когда при переходе по URL-адресу в браузере отображаются данные, но при использовании их в приложении возникает ошибка в журнал трассировки службы: Configuration evaluation context not found. Об этом говорится в другом вопросе.

Однако, если в sproc сопоставление полей 1: 1 с одним из объектов, в описанных выше шагах вместо выбора нового сложного типа выберите Entities и соответствующий объект, и это будет отлично работают в обоих случаях (URL-навигация и потребление).

class Program
{
    static void Main(string[] args)
    {
        DataServiceContext context = new DataServiceContext(new Uri("http://localhost:50100/DataService1.svc/"));
        IEnumerable<WHO_TYPES> result = context.Execute<WHO_TYPES>(new Uri("http://localhost:50100/DataService1.svc/GetDataWhoTypesSproc"));
        foreach (WHO_TYPES w in result)
        {
            Console.WriteLine(w.ID + "\t" + w.WHO_TYPE_NAME + "\t" + w.CREATED_DATE);
        }

        Console.Read();
    }
}

Обнаруженная проблема (неспособная вернуть сложные типы), похоже, является основной причиной этой проблемы, и более точно решена здесь .

...