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

时间:2009-07-06 04:46:20

标签: linq entity-framework include conditional

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

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

something like...

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

我明白这不是有效的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'

强调连接条件。

我觉得这对esql来说相当直接,但是我的偏好就是动态构建表达式树。

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

5 个答案:

答案 0 :(得分: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
                );
        }
    }
}

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

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

var dealers = query.ToArray().Select(o => o.Dealer);

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

答案 1 :(得分:6)

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

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

var count = dealership.Parts.Count();

我期待得到零件,而不是价格低于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")) };

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

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

答案 2 :(得分:1)

我错过了什么,或者您不只是在寻找Any关键字?

var query = dealerships.Where(d => d.parts.Any(p => p.price < 100.00) || 
                              d.parts.suppliers.Any(s => s.country == "brazil"));

答案 3 :(得分:0)

是的,这就是我想要做的事情我认为数据服务的下一个版本将有可能做到LINQ to REST查询,这些查询在我刚刚切换到加载逆转并包含相关实体的同时会很好这将被加载多次,但理论上它只需要在第一个包含中加载一次,就像在此代码中一样

return this.Context.SearchHistories.Include("Handle")
    .Where(sh => sh.SearchTerm.Contains(searchTerm) && sh.Timestamp > minDate && sh.Timestamp < maxDate);

在我尝试加载任何句柄之前,匹配逻辑的搜索历史但不知道如何使用你发布的包含逻辑,所以我认为反向查找将是一个不那么肮脏的解决方案

答案 4 :(得分:0)

我知道这可以使用一个包含。永远不要测试两个包含,但值得尝试:

.0
相关问题