LINQ to SQL:针对列表,数组和对象列表的高级查询

时间:2009-04-08 19:56:58

标签: c# linq linq-to-sql

单个和多个列表

请考虑以下列表:

List<Int32> appleIdentities = new List<int>(new[] { 1, 2, 3 });
List<Int32> chocolateIdentities = new List<int>(new[] { 2, 3, 4 });
List<Int32> icecreamIdentities = new List<int>(new[] { 11, 14, 15, 16 });

使用LINQ to SQL;是否有可能将一份声明转化为:

SELECT
    DesertsID,
    DesertsName
FROM
    Deserts
WHERE
    Deserts.AppleIdentity IN (1, 2, 3) AND
    Deserts.ChocolateIdentity IN (2, 3, 4) AND
    Deserts.IcecreamIdentity IN (11, 14, 15m 16)

如果是;如果我只想查询appleIdentities列表中的沙漠数据库,代码将如何显示?



阵列

考虑以下数组:

Int32[] appleIdentities = new[] {1, 2, 3, 4};
String[] chocolateNames = new[] {"Light", "Dark"};

使用LINQ to SQL;是否有可能将一份声明转化为:

SELECT
    DesertsID,
    DesertsName
FROM
    Deserts
WHERE
    Deserts.AppleIdentity IN (1, 2, 3) AND
    Deserts.ChocolateName IN ('Light', 'Dark')

如果是;如果我想仅仅针对appleIdentities数组查询沙漠数据库,代码将如何显示?



对象列表

请考虑以下事项:

public class Identities
{
    public Int32 appleIdentity { get; set; }
    public String chokolateName { get; set; }
}

List<Identities> identities = new List<Identities>(new[] {
    new Identities { appleIdentity = 1, chokolateName = "Light" },
    new Identities { appleIdentity = 2, chokolateName = "Dark" },
});

使用LINQ to SQL;是否有可能将一份声明转化为:

SELECT
    DesertsID,
    DesertsName
FROM
    Deserts
WHERE
    Deserts.AppleIdentity IN (1, 2) AND
    Deserts.ChocolateName IN ('Light', 'Dark')

如果是;如果我想查询我的沙漠数据库而不是appleIdentity - Identities对象列表中的属性,代码将如何显示?


这是LINQ to SQL query against a list of entities

的分支

4 个答案:

答案 0 :(得分:3)

  

如果我愿意,代码将如何显示   查询我的沙漠数据库   只是appleIdentities列表?

您可以在多个语句中组合linq查询,如此,并在运行时选择过滤您想要在where子句中使用的语句。

var query = db.Desserts;
if (filterbyAppleIdentity)
    query = query.Where( q => appleIdentities.Contains(q.DesertsID));
if (filterbyChocolateIdentities)
    query = query.Where( q => chocolateIdentities.Contains(q.DesertsID));
if (filterbicecreamIdentities)
    query = query.Where( q => icecreamIdentities.Contains(q.DesertsID));

var deserts = query.ToList();

你也可以在没有if语句的情况下写一个扩展方法来执行此操作:(编辑固定的拼写错误,返回类型应该是IQueriable

public static class LinqExtensions {
  public IQueriable<T> CondWhere<T>(this IQueriable<T> query, bool condition, Expression<Func<T,bool>> predicate) {
     if (condition)
        return query.Where(predicate);
     else 
        return query;
  }
 }

并编写你的linq查询:

  var deserts = db.Desserts;
      .CondWhere(filterbyAppleIdentity, q => appleIdentities.Contains(q.DesertsID));
      .CondWhere(filterbyChocolateIdentities, q => chocolateIdentities.Contains(q.DesertsID));
      .CondWhere(filterbicecreamIdentities, q => icecreamIdentities.Contains(q.DesertsID)).ToList();

另一种方法是联合id列表:

var deserts = db.Deserts
        .Where( d => appleIdentities.Union(chocolateIdentities).Union(icecreamIdentities).Contains(d.DesertsID);

有关可以使用的对象列表。选择扩展方法将列表投影到int或字符串IEnumerable中,您可以以相同的方式在查询中使用contains:

var deserts = db.Deserts
    .Where(d => 
        identities.Select(i => i.appleIdentity).Contains(d => d.DesertID) &&
        identities.Select(i => i.chokolateName).Contains(d => d.DesertsName)
     )

答案 1 :(得分:2)

好吧,你可以尝试:

var query = from dessert in db.Desserts
            where appleIdentities.Contains(dessert.AppleIdentity)
               && chocolateIdentities.Contains(dessert.ChocolateIdentity)
               && iceCreamIdentities.Contains(dessert.IceCreamIdentity)
            select new { dessert.Id, dessert.Name };

我相信这没关系,虽然当名单变得足够大时,它会失败。这应该适用于列表和数组。

我不确定你的第三个查询 - 我认为你需要为每个单独的Contains调用提供一个列表。

答案 2 :(得分:2)

当然 - 只需使用Contains - 以Northwind为例:

var qry = from cust in ctx.Customers
          where custIds.Contains(cust.CustomerID)
             && regions.Contains(cust.Region)
          select cust; // or your custom projection

答案 3 :(得分:2)

正如其他人所说,LinqToSql会将Contains翻译为IN

有一些警告:

  • 此翻译适用于List<T>.Contains(),但不适用于IList<T>.Contains()。它适用于数组吗?我不知道。
  • 这个翻译很乐意翻译你喜欢的元素 - 每个元素都成为一个sql参数。 SQL Server 2008有大约2000个参数限制,如果您尝试使用太大的集合,将抛出sql例外
  • 此转换应用于字符串集合时,将生成 nvarchar 参数。如果目标列是 varchar 并且您想要在此列上使用索引,则这可能是一个严重的问题。 Sql Server将转换索引,而不是参数...这涉及读取和转换整个索引中的每个字符串。

以下是对象列表问题的一些代码:

List<int> someIDs = identities
   .Select(x => x.appleIdentity).ToList();
List<string> someStrings = identities
   .Select(x => x.chokolateName).ToList();

var query = db.Desserts.Where(d =>
  someIDs.Contains(d.AppleIdentity) &&
  someStrings.Contains(d.ChocolateName)
  )