Предложение NOT IN в LINQ to Entities

Есть ли способ создать предложение not in, как это было бы в SQL Server в Linq для сущностей?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
49
0
141 996
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Пытаться:

from p in db.Products
where !theBadCategories.Contains(p.Category)
select p;

Какой SQL-запрос вы хотите преобразовать в Linq-запрос?

Ответ принят как подходящий

Если вы используете коллекцию в памяти в качестве фильтра, вероятно, лучше всего использовать отрицание Contains (). Обратите внимание, что это может не сработать, если список слишком длинный, и в этом случае вам нужно будет выбрать другую стратегию (см. Ниже для использования стратегии для полностью ориентированного на БД запроса).

   var exceptionList = new List<string> { "exception1", "exception2" };

   var query = myEntities.MyEntity
                         .Select(e => e.Name)
                         .Where(e => !exceptionList.Contains(e.Name));

Если вы исключаете на основе другого запроса к базе данных, лучше использовать Except. (Вот ссылка на сайт для поддерживаемых расширений Set в LINQ to Entities)

   var exceptionList = myEntities.MyOtherEntity
                                 .Select(e => e.Name);

   var query = myEntities.MyEntity
                         .Select(e => e.Name)
                         .Except(exceptionList);

Это предполагает сложную сущность, в которой вы исключаете определенные в зависимости от некоторого свойства другой таблицы и хотите, чтобы имена сущностей не исключались. Если вам нужна вся сущность, тогда вам нужно будет создать исключения как экземпляры класса сущности, чтобы они удовлетворяли оператору равенства по умолчанию (см. документы).

По какой-то причине Except выдает ужасный SQL. Contains - это метод, который можно использовать здесь: myEntities.MyEntity.Select(e => e.Name ).Where(x => !exceptionList.Contains(x)).

Gert Arnold 10.08.2013 03:28

@GertArnold, не могли бы вы уточнить выражение «производит ужасный SQL»? Я использую Except, и он работает нормально. Никаких странностей, ни причуд производительности, AFAIK.

NinjaCross 06.10.2014 20:00

@NinjaCross Оператор, как в ответе выше, производит SQL с n-1 предложениями UNION ALL, где n - количество элементов в exceptionList. Я просто пробовал с EF 6.1, так что дело не в том, что он улучшился или что-то в этом роде. В EF 4.1 то же самое, поэтому я просто не понимаю, почему этот ответ вообще был принят. Предлагающий Contains ответ правильный. Я думаю, вы использовали Except с другим IQueryable, поэтому EF смог преобразовать его в SQL EXCEPT. А ты?

Gert Arnold 06.10.2014 20:14

@GertArnold - not Contains вполне допустимо в пределах ограничения, согласно которому предложение NOT IN ограничивается примерно 2000 записями. После этого вы можете получить ошибку ресурсов SQL. Вероятно, это то, что я бы использовал в простом случае.

tvanfosson 06.10.2014 20:29

@GertArnold, вот что я делаю: (из e в dataModel.TABLE1 выберите e.ID) .Except (dataModel.TABLE2.Select (m => m.LightTypeID)). Min (); Это сгенерированный запрос: SELECT [GroupBy1]. [A1] AS [C1] FROM (SELECT MIN ([Except1]. [ID]) AS [A1] FROM (SELECT [Extent1]. [ID] AS [ID] FROM [dbo]. [TABLE1] AS [Extent1] EXCEPT SELECT [Extent2]. [LightTypeID] AS [LightTypeID] FROM [dbo]. [TABLE2] AS [Extent2]) AS [Except1]) AS [GroupBy1]

NinjaCross 06.10.2014 20:43

@NinjaCross Действительно, это два IQueryable с Except. Таким образом, все выражение содержит отображенные объекты и может быть переведено в SQL EXCEPT. Другое дело использование Except со списком в памяти. @tvanfosson Я знаю, но есть какое-то исправление: stackoverflow.com/q/24534217/861716. Except (со списком в памяти) выбрасывает "слишком глубоко вложенный" задолго до этих чисел. Можем ли мы сделать вывод, что Except в порядке, если задействованы только отображенные объекты, и что в остальном Contains лучше?

Gert Arnold 06.10.2014 20:58

@GertArnold Для примера в этом ответе да. В качестве общего ответа я думаю, что с EF, вероятно, лучше всего сказать «это зависит от обстоятельств» - проверьте свою производительность, выберите стратегию, которая работает лучше всего.

tvanfosson 06.10.2014 21:01

@GertArnold Я обновил ответ, чтобы устранить различные различия. В то время были другие ответы на этот случай, и я не хотел затрагивать ту же тему. Теперь, когда это старый и принятый ответ, я включил этот материал.

tvanfosson 06.10.2014 21:09

Я взял список и использовал,

!MyList.Contains(table.columb.tostring())

Примечание. Убедитесь, что вы используете List, а не Ilist.

У меня есть следующие методы расширения:

    public static bool IsIn<T>(this T keyObject, params T[] collection)
    {
        return collection.Contains(keyObject);
    }

    public static bool IsIn<T>(this T keyObject, IEnumerable<T> collection)
    {
        return collection.Contains(keyObject);
    }

    public static bool IsNotIn<T>(this T keyObject, params T[] collection)
    {
        return keyObject.IsIn(collection) == false;
    }

    public static bool IsNotIn<T>(this T keyObject, IEnumerable<T> collection)
    {
        return keyObject.IsIn(collection) == false;
    }

Применение:

var inclusionList = new List<string> { "inclusion1", "inclusion2" };
var query = myEntities.MyEntity
                     .Select(e => e.Name)
                     .Where(e => e.IsIn(inclusionList));

var exceptionList = new List<string> { "exception1", "exception2" };
var query = myEntities.MyEntity
                     .Select(e => e.Name)
                     .Where(e => e.IsNotIn(exceptionList));

Также очень полезно при прямой передаче значений:

var query = myEntities.MyEntity
                     .Select(e => e.Name)
                     .Where(e => e.IsIn("inclusion1", "inclusion2"));

var query = myEntities.MyEntity
                     .Select(e => e.Name)
                     .Where(e => e.IsNotIn("exception1", "exception2"));

Это полезно, но не может быть переведено на выражение магазина.

Marek Bar 26.04.2017 09:36

Верно, но я бы хотел выполнить в базе данных. AsEnumerable загрузит данные в память.

Marek Bar 26.04.2017 09:46

Я создал его более похожим на SQL способом, я думаю, что это легче понять

var list = (from a in listA.AsEnumerable()
            join b in listB.AsEnumerable() on a.id equals b.id into ab
            from c in ab.DefaultIfEmpty()
            where c != null
            select new { id = c.id, name = c.nome }).ToList();

Другие вопросы по теме