Сравнить локальный список с базой данных - PullRequest
0 голосов
/ 25 марта 2020

У меня есть локальный список с сущностями, несколько сотен, и у меня есть SQL Таблица серверов, где я храню идентификатор успешно обработанных сущностей, несколько миллионов. Я хотел бы знать, какие объекты из моего локального набора еще не обработаны, т.е. не находятся в таблице SQL.

Первый подход состоит в том, чтобы выполнить итерацию по локальному списку с помощью следующего оператора Linq:

Entity entity = db.Entities.FirstOrDefault(m => m.ID ==  ID);
if (entity == null)   { NewList.Add(ID) }

, тогда NewList будет содержать все новые объекты. Однако это очень медленно.

В LINQ, как бы вы отправили весь локальный список на сервер SQL одним вызовом, а затем вернули те, которых нет в таблице SQL?

Вам действительно нужно создать временную таблицу с моим локальным списком, затем присоединиться к уже обработанной таблице и вернуть пустые таблицы?

Ответы [ 2 ]

0 голосов
/ 25 марта 2020

Используйте метод .Contains для получения уже обработанных идентификаторов
и Except для создания списка еще не обработанных идентификаторов.

var localList = new List<int> { 1, 2, 3 };

var processed = db.Entities
    .Where(entity => localList.Contains(entity.Id))
    .Select(entity => entity.Id)
    .ToList();

var notProcessed = localList.Except(processed).ToList();

Это будет зависеть от провайдера, но .Contains должен сгенерировать sql нравится:

SELECT Id FROM Entity WHERE Id IN (1, 2, 3)
0 голосов
/ 25 марта 2020

предложение:

создайте временную таблицу и вставьте свои идентификаторы

выберите результат на стороне SQL

РЕДАКТИРОВАТЬ:

"Может Вы делаете это в LINQ? "

TL; DR:

да * но это уродливая работа, напишите SQL себя

*) зависит от того, что Вы имеете в виду «в» LINQ, потому что это не входит в сферу LINQ. Другими словами: выражение LINQ является одним слоем слишком абстрактным, но если вам случится иметь доступную для этого реализацию LINQ, вы можете использовать this в ваших операторах LINQ

в выражении LINQ на стороне у вас есть что-то вроде:

List<int> lst = new List<int>() { 1,2,3 };
List<int> result = someQueryable.Where(x=>lst.Contains(x.ID)).Select(x=>x.ID).ToList();

вопрос теперь такой: что происходит на стороне SQL (при условии, что запрашиваемые данные приводят нас к базе данных SQL)?

запрашиваемых провайдер (например, Entity Framework) каким-то образом должен перевести это в SQL, выполнить его и вернуться с результатом

, здесь будет место для изменения перевода ... например, 1026 *

исследовать дерево выражений относительно объекта, который является целью для вызова Contains (...), и если оно больше, чем просто несколько элементов, go для подхода временной таблицы ...

одно и то же выражение LINQ может быть переведено в различные команды SQL. Поставщик решает, как должен быть выполнен перевод.

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

Если вы не разрабатываете большой масштабируемый продукт, который будет развернут для работы с различными БД-бэкэндами, это, как правило, не стоит усилий ... более простой способ go - написать sql самостоятельно и просто используйте опцию sql вашего соединения с БД

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