在Entity Framework 4中过滤集合

4

我一直在测试EF 4,并希望筛选出对象的子集合。

我使用POCO支持,EF会自动连接我的集合:

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

在这个例子中,我可以获取一个分类的实例,然后枚举它的产品。我想知道的是,如何筛选这个集合,比如只返回活动产品。我知道我可以在内存中完成这个操作,但很重要的一点是标准直接发送到数据库。在NHibernate中,我可以在我的集合上使用过滤器来完成此操作,在EF 4中是否有类似的功能?我曾考虑过创建另一个集合,例如:
public virtual ICollection<Product> ActiveProducts {get;set;} 

但我不确定如何将它连接起来。

谢谢, Ben

2个回答

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);
    }
}

质量不太好,但希望能帮到你。

编辑:

另一种方法是

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


1

很遗憾,目前的Entity Framework版本官方并不支持这种操作。我花了一些时间研究了这个问题。我相当有信心,你可以通过一些基于反射的代码来改变默认行为,但我认为这会变得有些复杂。

我并不是DDD专家,但我认为更正确的做法是使用特定的查询来获取给定包含类类型实体的活动产品。你可以将其定位在存储库或查询类上。如果你需要出于效率原因防止他人访问此属性(这是我的情况),你可能需要将其从实体类中删除,并使你的查询成为访问活动产品的唯一方式。

如果您仍然想要进行数据库端的集合过滤,我的建议是覆盖代理类为每个属性拥有的委托字段。如果您从此博客文章查看生成的代理源代码中获取示例代码并使用RedGate的Reflector,您可以看到我所说的字段。它们将是具有名称ef_proxy_interceptorFor[PropertyName]的私有静态Func<[ProxyType],[PropertyType],[bool]>委托。返回值将确定getter方法是否返回基类的属性值或传递给委托的对象(前者为false,后者为true)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接