2015-10-28 5 views
0

Должен быть способ сравнить два набора результатов, оставаясь в LINQ. Вот мой существующий код, который использует HashSet сделать сравнение после двух отдельных запросов:LINQ: как получить пересечение двух наборов ints?

public static void AssertDealershipsShareTransactionGatewayCredentialIds(long DealershipLocationId1, 
     long DealershipLocationId2) 
    { 
     using (var sqlDatabase = new SqlDatabaseConnection()) 
     { 
      var DealershipCredentials1 = 
       sqlDatabase.Tables.DealershipLocationTransactionGateway 
        .Where(x => x.DealershipLocationId == DealershipLocationId1) 
        .Select(x => x.TransactionGatewayCredentialId); 
      var DealershipCredentials2 = 
       sqlDatabase.Tables.DealershipLocationTransactionGateway 
        .Where(x => x.DealershipLocationId == DealershipLocationId2) 
        .Select(x => x.TransactionGatewayCredentialId); 
      var doSetsOfCredentialsMatch = new HashSet<int>(DealershipCredentials1).SetEquals(DealershipCredentials2); 
      Assert.IsTrue(doSetsOfCredentialsMatch, 
       "The sets of TransactionGatewayCredentialIds belonging to each Dealership did not match"); 
     } 
    } 

Идей? Благодарю.

+2

Возможный дубликат запроса [Intersect LINQ query] (http://stackoverflow.com/questions/2381049/intersect-linq-query) –

+0

Что случилось с вашим путем? Выглядит идеально для меня. В противном случае см. Http://stackoverflow.com/questions/33245613/whats-the-best-way-to-determine-whether-two-listt-objects-contain- the-same-se и http://stackoverflow.com/questions/3669970/compare-two-listt-objects-for-equal-ignoring-order –

+0

Он делает два вызова базы данных, которые возвращают несколько записей, а не только логическое. –

ответ

0

Легкий ответ (Это позволит сделать 1, возможно 2 обращений к базе данных, оба из которых только возвращают логическое значение):

if (list1.Except(list2).Any() || list2.Except(list1).Any()) 
{ 
    ... They did not match ... 
} 

Лучше ответ (это будет сделать 1 вызов базы данных возвращает логическое значение):

var DealershipCredentials1 = 
    sqlDatabase.Tables.DealershipLocationTransactionGateway 
    .Where(x => x.DealershipLocationId == DealershipLocationId1) 
    .Select(x => x.TransactionGatewayCredentialId); 
var DealershipCredentials2 = 
    sqlDatabase.Tables.DealershipLocationTransactionGateway 
    .Where(x => x.DealershipLocationId == DealershipLocationId2) 
    .Select(x => x.TransactionGatewayCredentialId); 
if (DealershipCredentials1.GroupJoin(DealershipCredential2,a=>a,b=>b,(a,b)=>!b.Any()) 
    .Union(
     DealershipCredentials2.GroupJoin(DealershipCredential1,a=>a,b=>b,(a,b)=>!b.Any()) 
    ).Any(a=>a)) 
{ 
... They did not match ... 
} 

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

Другой подход, который является по существу такой же, как первый, но завернутые в одном LINQ, поэтому он всегда будет только сделать вызов 1 базы данных:

if (list1.Except(list2).Union(list2.Except(list1)).Any()) 
{ 
} 

И другой подход:

var common=list1.Intersect(list2); 
if (list1.Except(common).Union(list2.Except(common)).Any()) {} 
+0

Не будет проще 'Пересекать'? В любом случае оба подхода (или «Содержит») не применимы ни к одному классу. – varocarbas

+0

Intersect будет возвращать только записи, которые находятся в обоих наборах, а не сообщать вам, были ли какие-либо записи в одном, но не в обоих наборах. –

Смежные вопросы