【问题标题】:Linq to entities - searching in EntityCollection navigation propertiesLinq to entity - 在 EntityCollection 导航属性中搜索
【发布时间】:2009-11-08 10:30:46
【问题描述】:

我们有课

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

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

我们得到了IQueryable&lt;Invoice&gt;,我们没有得到IQueryable&lt;InvoicePosition&gt;。我应该如何找到包含 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(???);

但是我应该在哪里写什么呢?

编辑

将 Include("Position") 更改为 Include("Positions")。

编辑

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;

它似乎工作并且不影响 EF 包含。

【问题讨论】:

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


    【解决方案1】:

    以分数为基础的答案。如果你这样做:

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

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

    解决方法是编写您的查询,然后在最后应用包含。

    类似这样的:

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

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

    希望对你有帮助

    亚历克斯

    【讨论】:

    • 感谢您的提示。最后添加包含是有问题的,因为我使用存储库模式并且首先应用包含。中间解决方案(使用 Any())适合我。
    【解决方案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;
    

    【讨论】:

    • Invoice.Positions 是 EntityCollection。它没有 GroupName 属性。它有 InvoicePosition 列表。
    • 对不起,我误读了问题中的代码。我刚刚更新了答案。
    • 谢谢,现在它可以编译了,但不能很好地与 EF 一起使用。从存储库中获取时,我有 Include("Positions"),但我也有其他包含,并且在该操作期间它们丢失了。
    • 您应该能够将对 Include 的调用链接在一起,并且在查询后它们都应该在对象上保持填充状态。我需要更多信息才能告诉您其他包含丢失的原因。
    • 什么信息?我在 Profiler 中看到 EF 构造了其他查询,但它不包含已定义的 Includes。
    猜你喜欢
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多