2010-07-12 74 views
0

从出色答卷下面就我刚才的问题:Linq实体框架 - 我可以使用递归方法吗?

Linq Entity Framework generic filter method

我现在想了解如何申请类似递归到我的解决方案。

回顾一下采用这个方法的多个类似的声明,:

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

} 

我现在有一个接受的接口类型(IHideable)来操作在一个单一的实现:

protected IQueryable<TEntity> GetActiveEntities<TEntity>(ObjectSet<TEntity> entities) where TEntity : class , Database.IHideable { 

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

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

} 

该作品以及解决方案是干净的和可以理解的(非常感谢https://stackoverflow.com/users/263693/stephen-cleary)。

我现在要做的是将一个类似的(或相同的?)方法应用到任何EntityCollections关联到一个EntityObject,也碰巧实现IHideable。

我目前使用GetActiveEntities的()是这样的:

var products = GetActiveEntities(Entities.Products); 

return (

    from product in products 

    let latestOrder = product.Orders.FirstOrDefault( 
     candidateOrder => (
      candidateOrder.Date == product.Orders.Max(maxOrder => maxOrder.Date) 
     )  
    ) 

    select new Product() { 

     Id = product.Id , 
     Name = product.Name, 
     LatestOrder = new Order() { 

      Id = latestOrder.Id , 
      Amount = latestOrder.Amount, 
      Date = latestOrder.Date 

     } 

    } 

); 

在这个例子中,我想有订单EntityCollection也GetActiveEntities()过滤,从而使最新的顺序返回永远是“隐藏”一个。

是否有可能通过在GetActiveEntities()内部应用一些反射/递归并调用自己来实现IHideable的所有EntityCollections过滤?我说递归是因为最好的解决方案会通过实体图深入多个层次。

这东西正在伸展我的大脑!

更新#1(动了我的意见了这里)

感谢史蒂夫。

制作方法接受IQuerable的建议给出了这样的错误:

'System.Data.Objects.DataClasses.EntityCollection<Database.Order>' does not contain a definition for 'GetActiveEntities' and no extension method 'GetActiveEntities' accepting a first argument of type 'System.Data.Objects.DataClasses.EntityCollection<Database.Order>' could be found (are you missing a using directive or an assembly reference?) 

我相信这是因为EntityCollection没有实现IQueryable的。

我能够通过创建显式接受EntityCollection并返回IEnumerable的第二个扩展方法来获得更多。这编译但在运行了这个错误:

LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable`1[Database.Order] GetActiveEntities[Order](System.Data.Objects.DataClasses.EntityCollection`1[Database.Order])' method, and this method cannot be translated into a store expression. 

我也试过在EntityCollection调用AsQueryable已()并返回IQueryable的,但同样的错误回来。

回答

2

被修改为使用对象集代替EntityCollection

我建议使用我的解决方案,但作为一个扩展方法,该方法可以适用于任何的查询:

public static IQueryable<TEntity> WhereActive<TEntity>(
    this IQueryable<TEntity> entities) 
    where TEntity : class , Database.IHideable 
{ 
    var allowedStates = new string[] { "Active", "Pending" }; 

    return (
     from entity in entities 
     where allowedStates.Contains(entity.State) 
      && entity.Hidden == "No" 
     select entity 
    ); 
} 

这可以被用来作为例如:

var products = Entities.Products.WhereActive(); 

return (

    from product in products 

    let latestOrder = (
     from order in Entities.Orders.WhereActive() 
     where order.ProductId == product.Id 
     orderby candidateOrder.Date descending 
     select order).FirstOrDefault() 

    select new Product() 
    { 
     Id = product.Id, 
     Name = product.Name, 
     LatestOrder = new Order() 
     { 
      Id = latestOrder.Id, 
      Amount = latestOrder.Amount, 
      Date = latestOrder.Date 
     } 
    } 
); 
+0

感谢您的回复Stephen。实际上,我今天早些时候将该方法重构为扩展方法,但不想陷入这个例子,因此使用了方法调用。很高兴知道这是正确的举措 - 大部分C#语言功能对我来说都是新手。 – FantasticJamieBurns 2010-07-12 19:16:16

+0

谢谢史蒂夫,我已将我的意见转移到问题区域以便阅读...... – FantasticJamieBurns 2010-07-12 19:30:52

+0

您是对的:'EntityCollection'不实施'IQueryable'。我更新了我的答案,使用'Entities.Orders'而不是'product.Orders',它应该可以工作。 (我也改变了'latestOrder'计算以使用'orderby')。 – 2010-07-12 19:43:36