简体   繁体   中英

LINQ: how to get an intersection of two sets of ints?

There must be a way to compare two sets of results while staying in LINQ. Here's my existing code that uses a HashSet to do the comparison after two separate queries:

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

Ideas? Thanks.

Easy answer (This will make 1, possibly 2 database calls, both of which only return a boolean):

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

Better answer (This will make 1 database call returning a boolean):

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

The second method works by unioning a left outer join that returns a boolean indicating if any unmatching records were found with a right outer join that does the same. I haven't tested it, but in theory, it should return a simple boolean from the database.

Another approach, which is essentially the same as the first, but wrapped in a single LINQ, so it will always only make 1 database call:

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

And another approach:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM