有条件的包含在linq中的实体?

tim*_*tim 21 linq conditional entity-framework include

我觉得以下应该是可能的我只是不确定采取什么方法.

我想要做的是使用include方法来塑造我的结果,即定义沿着对象图遍历的距离.但是......我希望这种遍历是有条件的.

something like...

dealerships
    .include( d => d.parts.where(p => p.price < 100.00))
    .include( d => d.parts.suppliers.where(s => s.country == "brazil"));
Run Code Online (Sandbox Code Playgroud)

我知道这不是有效的linq,事实上,它是非常错误的,但实质上我正在寻找一些方法来构建一个表达树,它将返回形状结果,相当于......

select *
from dealerships as d
outer join parts as p on d.dealerid = p.dealerid
    and p.price < 100.00
outer join suppliers as s on p.partid = s.partid
    and s.country = 'brazil'
Run Code Online (Sandbox Code Playgroud)

重点是加入条件.

我觉得这对esql来说是相当直接的,但我最喜欢的是动态构建表达式树.

一如既往,感谢任何建议或指导

Jak*_*sen 15

这应该做的伎俩:

using (TestEntities db = new TestEntities())
{
    var query = from d in db.Dealership
                select new
                {
                    Dealer = d,
                    Parts = d.Part.Where
                    (
                        p => p.Price < 100.0 
                             && p.Supplier.Country == "Brazil"
                    ),
                    Suppliers = d.Part.Select(p => p.Supplier)
                };

    var dealers = query.ToArray().Select(o => o.Dealer);
    foreach (var dealer in dealers)
    {
        Console.WriteLine(dealer.Name);
        foreach (var part in dealer.Part)
        {
            Console.WriteLine("  " + part.PartId + ", " + part.Price);
            Console.WriteLine
                (
                "  " 
                + part.Supplier.Name 
                + ", " 
                + part.Supplier.Country
                );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码将为您提供经销商列表,每个经销商都包含已过滤的部件列表.每个部分都引用了供应商.有趣的是,您必须以所示方式在select中创建匿名类型.否则,经销商对象的Part属性将为空.

此外,您必须在从查询中选择经销商之前执行SQL语句.否则,经销商的Part属性将再次为空.这就是我将ToArray()调用放在以下行中的原因:

var dealers = query.ToArray().Select(o => o.Dealer);
Run Code Online (Sandbox Code Playgroud)

但我同意Darren的观点,这可能不是您图书馆用户所期望的.

  • 这要求您返回匿名类型而不是带有实际引用的原始类型.这"确实有效"但让我想要一个解决方案来返回原始对象,并将实际的集合对象过滤到我实际想要返回的内容.匿名返回类型确实有效......但实际上并不是真正理想的解决方案. (6认同)
  • 关于这个的说明,我尝试了这个,它最初没有用.我最终发现我启用了Lazy Loading,导致这种情况无法正常工作.一旦我关闭延迟加载,这就像一个魅力.谢谢Jakob! (2认同)

Dar*_*ren 6

你确定这是你想要的吗?我问的唯一原因是,一旦您在经销商的零件上添加过滤器,您的结果就不再是经销商.您处理的特殊对象在很大程度上非常接近经销商(具有相同的属性),但"部件"属性的含义是不同的.它不是经销商和零件之间的关系,而是过滤关系.

换句话说,如果我从你的结果中抽出经销商并传递给我写的方法,然后在我的方法中我打电话:

var count = dealership.Parts.Count();
Run Code Online (Sandbox Code Playgroud)

我期待得到零件,而不是价格低于100美元的巴西过滤零件.

如果您不使用经销商对象传递过滤后的数据,则变得非常容易.它变得如此简单:

    var query = from d in dealerships
               select new { DealershipName = d.Name, 
CheapBrazilProducts = dealership.Parts.Where(d => d.parts.Any(p => p.price < 100.00) || d.parts.suppliers.Any(s => s.country == "brazil")) };
Run Code Online (Sandbox Code Playgroud)

如果我只是像你要求的那样得到过滤后的集合,我可能会使用上面提到的技术,然后使用像Automapper这样的工具将过滤后的结果从我的匿名类复制到真正的类.它不是非常优雅,但它应该工作.

我希望有所帮助!这是一个有趣的问题.