LINQ to SQL: расширенные запросы к спискам, массивам и спискам объектов - PullRequest
3 голосов
/ 08 апреля 2009

Один и несколько списков

Рассмотрим следующие списки:

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 на список объектов

Ответы [ 4 ]

3 голосов
/ 09 апреля 2009

как бы выглядел код, если бы я хотел запросить мою базу данных пустынь против просто список 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();

Еще один способ сделать это - объединить списки идентификаторов:

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

Для списка объектов вы можете использовать метод расширения .Select, чтобы спроецировать ваш список в int или строку IEnumerable, и вы можете использовать в запросе тот же способ:

var deserts = db.Deserts
    .Where(d => 
        identities.Select(i => i.appleIdentity).Contains(d => d.DesertID) &&
        identities.Select(i => i.chokolateName).Contains(d => d.DesertsName)
     )
2 голосов
/ 09 апреля 2009

Как уже говорили другие, 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)
  )
2 голосов
/ 09 апреля 2009

Конечно - просто используйте Contains - используя Northwind в качестве примера:

var qry = from cust in ctx.Customers
          where custIds.Contains(cust.CustomerID)
             && regions.Contains(cust.Region)
          select cust; // or your custom projection
2 голосов
/ 09 апреля 2009

Ну, вы можете попробовать:

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 };

Полагаю, это нормально, хотя это не удастся, когда списки станут достаточно большими IIRC. Это должно быть хорошо для списков и массивов.

Я не уверен насчет вашего третьего запроса - думаю, вам понадобится список для каждого из отдельных вызовов Contains.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...