Метод универсального фильтра Linq Entity Framework - PullRequest
3 голосов
/ 10 июля 2010

У меня есть несколько методов, которые выполняют стандартный фильтр данных из моих сущностей (используя Entity Framework v4).

Пример № 1:

protected IQueryable<Database.Product> GetActiveProducts( ObjectSet<Database.Product> products ) {

    var allowedStates = new string[] { "Active" , "Pending" };

    return (
        from product in products
        where allowedStates.Contains( product.State )
            && product.Hidden == "No"
        select product
    );

}

Пример № 2:

protected IQueryable<Database.Customer> GetActiveProducts( ObjectSet<Database.Customer> customers ) {

    var allowedStates = new string[] { "Active" , "Pending" };

    return (
        from customer in customers
        where allowedStates.Contains( customer.State )
            && customer.Hidden == "No"
        select customer
    );

}

Как видите, эти методы идентичны, за исключением типов сущностей, с которыми они работают. У меня есть более 10 таких методов, по одному для каждого типа сущностей в моей системе.

Я пытаюсь понять, как у меня может быть 1 единственный метод, для которого я могу передать любой тип сущности, и заставить его выполнить предложение where, если существуют 2 поля / свойства.

Я не использую Inheritance в базе данных, поэтому, что касается системы, то случайно, что каждый из типов Entity имеет поля «Hidden» и «State».

Мой Googling говорит мне, что это как-то связано со сборкой кода с использованием Expression.Call (), но моя голова вращается!

Ответы [ 2 ]

6 голосов
/ 10 июля 2010

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

Обновлено, чтобы включить ограничение класса (см. Комментарий Марка)

public interface IHideable
{
  string State { get; }
  string Hidden { get; }
}

...

namespace Database
{
  public partial class Product : IHideable { }
  public partial class Customer : IHideable { }
}

...

protected IQueryable<T> GetActive<T>(ObjectSet<T> entities)
    where T : class, IHideable
{
  var allowedStates = new string[] { "Active" , "Pending" };    

  return (    
    from obj in entities
    where allowedStates.Contains(obj.State)
        && obj.Hidden == "No"
    select obj
  );
}  
3 голосов
/ 20 декабря 2010

Я хотел сделать то же самое с IQueryable<T> в качестве типа входного параметра для универсального метода.

Я получил исключение времени выполнения "Невозможно привести тип .... LINQ to Entities поддерживает только приведение типов примитивов модели данных Entity".

Через некоторое время я узнал, что забыл добавить ограничение класса для универсального параметра. Однако IQueryable<T> не требует наличия ограничения класса, оно все еще необходимо для разрешения типов во время выполнения.

Это заняло бы у меня часы без этого поста. Спасибо:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...