Как применить самостоятельное соединение в Linq Query? - PullRequest
2 голосов
/ 27 июня 2019

Таблица книг

Id  VendorId   ASIN   Price
--  --------   ----   ------
 1   gold123    123     10
 2   sil123     123     11
 3   gold456    456     15
 4   gold678    678     12
 5   sil456     456     12
 6   gold980    980     12

Я хочу написать запрос linq, который будет возвращать мне строки, для которых соответствует каждый золото , если sil идентификатор поставщика не существует,Последние три цифры идентификатора поставщика соответствуют столбцу ASIN в этой строке.

Например, для золота123 существует соответствующий sil123, так что строка не будет возвращена, а для золота 678 и золота980 соответствующий sil не существует.Таким образом, эти строки будут возвращены.

Я попытался выполнить следующие действия:

     var gold = _repository.Query<Books>().Where(x => 
                  x.VendorId.Contains("gold"))
                 .OrderBy(x => x.Id).Skip(0).Take(500).ToList();

    var asinsForGold = gold.Select(x => x.ASIN).ToList();



  var correspondingSilver = _repository.Query<Books>().Where(x => 
                            x.VendorId.Contains("sil") 
                           && asinsForGold.Contains(x.ASIN)).ToList();

var correspondingSilverAsins = correspondingSilver.Select(x => x.ASIN).ToList();

var goldWithoutCorrespondingSilver = gold.Where(x => 
                                !correspondingSilverAsins.Contains(x.ASIN));

Можем ли мы применить самосоединение или лучший способ получить результат только в одном запросе вместо двух запросов и нескольких других операторов списка.

Ответы [ 2 ]

2 голосов
/ 27 июня 2019

Это просто еще один предикат, «где соответствующего поставщика серебра не существует»:

var goldWoSilver = _repository.Query<Books>()
    .Where(x => x.VendorId.Contains("gold"))
    .Where(x => !_repository.Query<Books>()
        .Any(s => s.ASIN == x.ASIN
               && s.VendorId.Contains("sil"))
    .OrderBy(x => x.Id).Skip(0).Take(500).ToList();

Во многих случаях это удачный рецепт: начните запрос с сущности, которую вы хотите вернуть, и добавьте только предикаты. В общем случае объединения не следует использовать для фильтрации, а только для сбора связанных данных, хотя в этом случае следует использовать свойства навигации, которые неявно переводятся в объединения SQL.

0 голосов
/ 27 июня 2019

Посмотрите, поможет ли это -

var goldWithoutCorrespondingSilver = from b1 in books
                                  join b2 in books on b1.ASIN equals b2.ASIN
                                  where b1.VendorId.Contains("gold")
                                  group b2 by b1.VendorId into g
                                  where !g.Any(x => x.VendorId.Contains("sil"))
                                  select g.FirstOrDefault();

То, что я сделал, это -

  • Выбранные записи с совпадающими ASIN
  • Сгруппированы по VendorID
  • Выбранные, которые не имеют sil
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...