使用长where子句的Linq

3

有没有更好的方法来处理这个问题?我尝试遍历partsToChange集合并构建where子句,但它们被AND在一起而不是OR。我也不想在partsToChange列表中显式地执行每个项的等式操作。

var partsToChange = new Dictionary<string, string> {
    {"0039", "Vendor A"},
    {"0051", "Vendor B"},
    {"0061", "Vendor C"},
    {"0080", "Vendor D"},
    {"0081", "Vendor D"},        
    {"0086", "Vendor D"},
    {"0089", "Vendor E"},
    {"0091", "Vendor F"},
    {"0163", "Vendor E"},
    {"0426", "Vendor B"},
    {"1197", "Vendor B"}
};

var items = new List<MaterialVendor>();
foreach (var x in partsToChange)
{
    var newItems = (
    from m in MaterialVendor 
    where 
        m.Material.PartNumber == x.Key 
        && m.Manufacturer.Name.Contains(x.Value)
    select m
    ).ToList();
    items.AddRange(newItems);
}

额外信息:我正在LINQPad中工作,这是一个LinqToSql查询。在这里,MaterialVendor既是一个类,也是一个DataContext表。

编辑:LinqToSql细节。

这似乎是我找到的最好的方法,既易读又能减少复杂性。它还带有一种匿名类型的附加好处,不需要显式定义集合类型。这意味着我可以用匿名类型来变化返回的内容。

var predicate = PredicateBuilder.False<MaterialVendor>();

foreach (var x in partsToChange)
{
    var item = x;
    predicate = predicate.Or (m =>
        m.Material.PartNumber == item.Key 
        && m.Manufacturer.Name.Contains(item.Value));
}

var items = from m in MaterialVendor.Where(predicate)
    select m;

7
重点不在于你的where条件语句有多长,而在于你如何使用它。 - Muad'Dib
你在这里将MaterialVendor同时作为IEnumerable<T>和一个类。它到底是哪个? - BlueRaja - Danny Pflughoeft
1
那是一个相当简短的where子句。 - Randolpho
短小的从句,但有一长串的标准。 - Jeremy Roberts
3个回答

8

[编辑] 更好的是,由于partsToChange是一个字典

var items = MaterialVendor.Where(m =>
                m.Manufacturer.Name.Contains(partsToChange[m.Material.PartNumber])
            ).ToList();

尝试查询数据库时,抛出以下异常: 方法“System.String get_Item(System.String)”没有受支持的 SQL 翻译。 - Jeremy Roberts
@Jeremy:你在问题中发布的代码有效吗?我的之前的编辑有效吗? - BlueRaja - Danny Pflughoeft
你不能使用除了 IList.Contains(...) 以外的任何数据结构与 L2S 表进行交叉查询,而该方法会被转换为 IN (...) - cjk

2

请查看PredicateBuilder

使用PredicateBuilder,您可以在循环内构建Linq to sql表达式,并在必要时添加AND / OR子句,然后在最后一次执行。


0

where子句的大小并不重要。在循环内查询是降低可维护性和性能的部分。

List<MaterialVendor> items = 
(
  from z in MaterialVendor
  let partKey = z.Material.PartNumber
  where partsToChange.ContainsKey(partKey)
  let partValue = partsToChange[partKey]
  where z.Manufacturer.Name.Contains(partValue)
  select z
).ToList();

既然我们知道涉及到linq to sql...这里有一个混合模式查询。

List<string> keys = partsToChange.Keys.ToList();

List<MaterialVendor> items =  
( 
  from z in MaterialVendor 
  let partKey = z.Material.PartNumber 
  where keys.Contains(partKey)
  select new {MatVendor = z, Name = z.Manufacturer.Name, Key = partKey}
).AsEnumerable()
.Where(x => x.Name.Contains(partsToChange[x.partKey]))
.Select(x => x.MatVendor)
.ToList(); 

尝试查询数据库时,抛出以下异常:方法“Boolean ContainsKey(System.String)”没有受支持的SQL翻译。 - Jeremy Roberts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接