2010-07-28 63 views
1

我试图通过EF返回的结果中过滤下来到只有那些有关 - 在下面那些在一年(formattedYear)和订单类型的例子(filtOrder)过滤实体框架的图形对象

我有一个简单的一组对象

PEOPLE 1-M订单1-M的ORDERLINES

与在Model.edmx已经定义这些关系

在SQL我会做这样的事情......

SELECT * FROM人民内的连接顺序上ORDERS.PEOPLE_RECNO = PEOPLE.RECORD_NUMBER 内上ORDERLINE.ORDER_RECNO = ORDERS.RECORD_NUMBER加入ORDERLINE 其中[email protected][email protected]

我试过几个方法...

 var y = _entities.PEOPLE.Include("ORDERS").Where("it.ORDERS.ORDER_KEY=" + filtOrder.ToString()).Include("ORDERLINEs").Where("it.ORDERS.ORDERLINEs.SERVICE_YEAR='" + formattedYear + "'"); 

     var x = (from hp in _entities.PEOPLE 
       join ho in _entities.ORDERS on hp.RECORD_NUMBER equals ho.PEOPLE_RECNO 
       join ol in _entities.ORDERLINEs on ho.RECORD_NUMBER equals ol.ORDERS_RECNO 
       where (formattedYear == ol.SERVICE_YEAR) && (ho.ORDER_KEY==filtOrder) 
       select hp 
       ); 

Ÿ失败ORDER_KEY不是transient.collection的一员...... 和X返回正确的人,但他们都他们的订单附 - 不只是我所追求的。

我想我错过了一些简单的东西?

回答

3

想象一下,你有一个有100个订单的人。现在您将这些订单过滤为10.最后,您选择具有这些订单的人员。你猜怎么了?该人仍然有100个订单!

你要求的不是实体,因为你不想要整个实体。你似乎想要的是实体数据的一个子集。所以项目:

var x = from hp in _entities.PEOPLE 
     let ho = hp.ORDERS.Where(o => o.ORDER_KEY == filtOrder 
             && o.ORDERLINES.Any(ol => ol.SERVICE_YEAR == formattedYear)) 
     where ho.Any() 
     select new 
     { 
      Id = hp.ID, 
      Name = hp.Name, // etc. 
      Orders = from o in ho 
        select new { // whatever 
     }; 
+0

看起来不错,但是,如果你需要在另一个方法中使用结果(想象这是在DAL中完成的),使用匿名对象可能是个问题......难道不可能返回一个People对象吗?我们会失去应用于订单的过滤器吗? – 2010-07-28 13:00:24

+0

克雷格 - 是的,我明白,但要避免匿名对象的原因朱利安提到的原因。我只是希望我的存储库能够返回具有正确数据的人员,并将其交给强制类型的视图,而在其他情况下,这些视图可能与整个数据集一起工作。 – Andiih 2010-07-28 13:09:04

+3

如果需要,您可以返回POCO而不是匿名类型(只需在'new'和'{')之间输入类型名称“即可)。但是,您不能返回实体类型,因为EF不允许部分构造的实体。 – 2010-07-28 13:14:36

1

我不完全确定你的问题是什么,但以下可能会有所帮助。

在实体框架中,如果你想加载一个对象图并过滤这些子对象,那么你可能首先对子对象进行查询并枚举它(即调用ToList()),以便childern在内存中获取。

然后,当您获取父对象(并且不使用.include)时,实体框架将能够自行构造图(但请注意,您可能必须先禁用延迟加载,否则加载时间会很长) 。 这里有一个例子(假设你的上下文是“DB”):

db.ContextOptions.LazyLoadingEnabled = false; 

var childQuery = (from o in db.orders.Take(10) select o).ToList(); 

var q = (from p in db.people select p).ToList(); 


现在你会发现,所有的人都反对有十阶对象的


编辑:我是在当我写样本代码的时候很匆忙,因此我还没有对它进行测试,我可能会因为声称这个问题而出错.Take(10)会为每个人物带回十个命令,相反我相信.Take(10) )将在延迟加载禁用时仅返回十个整体订单d,(对于启用延迟加载的情况,我必须实际测试结果是什么),并且要为每个人员对象返回十个订单,您可能需要执行更多的过滤。

但这个想法很简单,你首先获取所有的子对象和实体框架自己构造图。

+0

前段时间,我走下了POCO路线,但这是一个有趣的残疾加载,ToList和子查询的副作用:我将在未来记住它。 – Andiih 2011-03-02 09:07:07

+0

无论是否启用延迟加载,它都能正常工作,但提到延迟加载时我试图提出的一点是,虽然背后的理论背后的理论是因为孩子在加载父代时应该在内存中仍然是延迟加载,这也需要仔细考虑延迟加载时的结果。 – 2011-09-20 16:01:32