Linq to entities - 在EntityCollection导航属性中搜索

时间:2009-11-08 10:30:47

标签: linq entity-framework linq-to-entities

我们有课程

public Invoice: EntityObject
{
    public EntityCollection<InvoicePosition> Positions { get {...}; set{...}; }
    ...
}

public InvoicePosition: EntityObject
{
    public string GroupName { get {...}; set{...}; }
}

我们获得IQueryable<Invoice>,我们未获得IQueryable<InvoicePosition>。我应该如何找到有仓位的发票,其中GroupName是'Fuel'?

IQueryable<Invoice> invoices = InvoiceRepository.List();
IQueryable<Invoice> invoicesThatHaveFuelPositions = 
    from i in invoices
    where ?
    select i

EntityFramework应该能够将其转换为正确的SQL查询。

修改

Mark Seemann写道,我可以使用:

IQueryable<Invoice> invoices = InvoiceRepository.List().Include("Positions").Include("OtherInclude");
IQueryable<Invoice> invoicesThatHaveFuelPositions = 
    from i in invoices
    from p in i.Positions
    where p.GroupName = 'Fuel'
    select i;

有一个问题。当我使用这个过滤时,我失去了“OtherInclude”。我认为这在使用EF时不是正确的过滤方式。我必须将其更改为:

IQueryable<Invoice> invoices = InvoiceRepository.List().Include("Positions").Include("OtherInclude");
IQueryable<Invoice> invoicesThatHaveFuelPositions = invoices.Where(???);

但是我应该在Where中写什么?

修改

将包含(“职位”)更改为包含(“职位”)。

修改

亚历克斯·詹姆斯给出了提示(http://blogs.msdn.com/alexj/archive/2009/06/02/tip-22-how-to-make-include-really-include.aspx)的链接,这表明:

IQueryable<Invoice> invoicesThatHaveFuelPositions = 
    from i in invoices
    where i.Positions.Any(p => p.GroupName == 'Fuel')
    select i;

它似乎有效,并不影响EF包括。

2 个答案:

答案 0 :(得分:5)

以Marks答案为基础。如果你这样做:

var q = from i in invoices.Include("something")
        from p in i.Positions
        where p.GroupName == "Fuel"
        select i;

包含丢失(请参阅this tip),因为如果查询的形状发生变化,EF会丢失所有包含,例如,如果您在SelectMany查询中执行隐式连接,又来自from。

解决方法是编写查询,然后在最后应用Include。

这样的事情:

var q = ((from i in invoices
        from p in i.Positions
        where p.GroupName == "Fuel"
        select i) as ObjectQuery<Invoice>).Include("something");

如果您这样做,实体框架实际上会执行包含。

希望这有帮助

亚历

答案 1 :(得分:2)

这样的事情应该有效:

var q = from i in invoices
        from p in i.Positions
        where p.GroupName == "Fuel"
        select i;

但是,它使用导航属性Positions,默认情况下未加载(实体框架使用显式加载)。但是,如果invoices变量是这样创建的,它将起作用:

var invoices = from i in myObjectContext.Invoices.Include("Positions")
               select i;