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

Luk*_*Led 5 linq linq-to-entities entity-framework

我们有课

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

public InvoicePosition: EntityObject
{
    public string GroupName { get {...}; set{...}; }
}
Run Code Online (Sandbox Code Playgroud)

我们得到了IQueryable<Invoice>,我们没有得到IQueryable<InvoicePosition>.我应该如何找到有位置的发票,其中GroupName是'Fuel'?

IQueryable<Invoice> invoices = InvoiceRepository.List();
IQueryable<Invoice> invoicesThatHaveFuelPositions = 
    from i in invoices
    where ?
    select i
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

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

IQueryable<Invoice> invoices = InvoiceRepository.List().Include("Positions").Include("OtherInclude");
IQueryable<Invoice> invoicesThatHaveFuelPositions = invoices.Where(???);
Run Code Online (Sandbox Code Playgroud)

但是我应该在哪里写?

编辑

已将包含("职位")更改为包含("职位").

编辑

Alex James给出了提示链接(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;
Run Code Online (Sandbox Code Playgroud)

它似乎工作,并不影响EF包括.

Ale*_*mes 5

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

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

包含丢失(请参阅此提示),因为如果查询的形状发生更改,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");
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助

亚历克斯