2010-07-01 3 views
4

Я тестировал EF 4 и собираюсь фильтровать дочерние коллекции на объект.Фильтрация коллекций в Entity Framework 4

Я использую поддержку POCO и имею EF электромонтажные мои коллекции автоматически:

 public virtual ICollection<Product> Products { get; set; } 

Таким образом, в этом примере, я могу получить экземпляр категории, а затем перечислить его продукты.

Что я хочу знать, так я могу отфильтровать эту коллекцию, скажем, чтобы возвращать только активные продукты. Я знаю, что могу сделать это в памяти, но важно, чтобы критерии отправлялись напрямую в базу данных.

В NHibernate я могу сделать это, используя фильтры в своей коллекции, есть ли что-то эквивалентное в EF 4?

Я действительно думал о создании другой коллекции, например.

public virtual ICollection<Product> ActiveProducts {get;set;} 

но я не уверен, как это сделать.

Спасибо, Бен

ответ

1

К сожалению, это официально не возможно с текущей версией Entity Framework. Я тоже некоторое время погружался в эту проблему. Я достаточно уверен, что вы можете заставить его работать с некоторым кодом на основе отражения, где вы меняете поведение по умолчанию, но я думаю, что это будет несколько сложнее.

Я едва ли являюсь экспертом DDD, но я думаю, что более правильный способ сделать это - использовать конкретный запрос для получения активных продуктов, заданных сущностью типа вашего содержащего класса. Вы можете найти это в репозитории или в классе запросов. Если вам необходимо запретить другим пользователям доступ к этому свойству по соображениям эффективности (это мой случай), вы, вероятно, захотите удалить его из класса сущности и сделать свой запрос единственным способом доступа к активным продуктам.

Если вы все еще хотите сделать фильтрацию коллекции db-side, мое предложение состоит в том, чтобы переопределить поле делегата, которое имеют классы прокси для каждого свойства. Если вы возьмете пример кода из этого сообщения в блоге на viewing generated proxy source и используете Reflector от RedGate, вы можете увидеть поля, о которых я говорю. Они будут частным статическим Func < [ProxyType], [PropertyType], [bool]> делегаты с именами ef_proxy_interceptorFor [PropertyName]. Возвращаемое значение будет определять, возвращает ли getter значение свойства базового класса или объект, переданный делегату (false для первого, true для последнего).

1

Я знаю простой обходной путь, не очень аккуратно (ИМХО)

var idCategory = *get from somewhere*; 
var db = new MyContext(); 
var activeProducts = db.Products.ActiveByCategory(idCategory); 

и расширение что-то вроде этого

public static class Extensions { 
    public static IQueryable<Product> ActiveByCategory(this IQueryable<Product> source, int idCategory) { 
     return source.Where(p => p.CategoryId == idCategory && p.Active); 
    } 
} 

бедных, но надеюсь, что это поможет в любом случае

EDIT :

другой способ

var activeProducts = db.Categories.Where(c => c.Id == idCategory).SelectMany(c => c.Products).Where(p => p.Active); 

запрос генерируемый

SELECT 
[Extent1].[CategoryId] AS [CategoryId], 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name] 
[Extent1].[Active] AS [Active] 
FROM [dbo].[Products] AS [Extent1] 
WHERE (2 = [Extent1].[CategoryId]) AND ([Extent1].[Active] = 'true') 

2 = idCategory

Смежные вопросы