关于.net:C#LINQ在两个不同的数据集上使用条件where子句连接

C# LINQ join with conditional where clause on two different data sets

我有两个集合要与之比较数据。我可以通过ID加入这两个集合。我需要有一个WHERE子句,它返回集合A中找不到集合B中某些项的数据列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    public class Contract
    {
        public string ContractId { get; set; }
        public IList InvoiceList { get; set; }

        public class Invoice
        {
            public int InvoiceNumber { get; set; }
        }
    }

    public class PaymentRequest
    {
        public IList Contracts { get; set; }
        public class ContractList
        {      
            public string ContractId { get; set; }  
            public IList Invoices { get; set; }
        }

        public class InvoiceList
        {          
            public int InvoiceNumber { get; set; }
        }
    }

到目前为止,我有以下几点,但还不能完全理解WHERE子句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    var query = (
    from request in (
        from contract in paymentRequest.Contracts                    
        from invoice in contract.Invoices
        select new { contract, invoice })
    join valid in (
        from contract in validContracts
        select new { contract })              
    on new { request.contract.ContractId } equals new { valid.contract.ContractId }
    where !(
        // get a list of invoice numbers in the request data set that are not in the valid data set
    )
    select"Contract Id:" + request.contract.ContractId +
          ", Invoice Number:" + request.invoice.InvoiceNumber
).ToList();

感谢您的帮助。


1
2
3
var collectionAIds = new HashSet<int>(collectionA.Select(colAItem => colAItem.Id));
var itemsInCollectionBNotInCollectionA = collectionB.Where(colBItem =>
                                             !collectionAIds.Contains(colBItem.Id));

基本上,我们要获取集合A中的ID,然后从集合B中选择所有项,而不是A的ID列表中。

哈希集是可选的。如果不使用该变量,它只会避免重复的O(N)查找。

P.S.我假设int是ID的类型。为哈希集使用ID的数据类型。


在我看来,您的查询应该如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var query =
(
    from request in
    (
        from contract in paymentRequest.Contracts                    
        from invoice in contract.Invoices
        select new { contract, invoice }
    )
    join valid in
    (
        from contract in validContracts
        select new { contract }
    ) on new { request.contract.ContractId } equals new { valid.contract.ContractId } into gvs
    where
        gvs
            .SelectMany(gv => gv.contract.Invoices)
            .Select(i => i.InvoiceNumber)
            .All(n => n != request.invoice.InvoiceNumber)
    select"Contract Id:" + request.contract.ContractId +
          ", Invoice Number:" + request.invoice.InvoiceNumber
).ToList();


与提醒常规SQL查询的功能相比,使用contains会降低性能。这样会更好

1
2
3
4
5
var result =
    from itm1 in Coll1
    from itm2 in Coll2.Where(x => x.Id == itm1.Id).DefaultIfEmpty()
    where itm2 == null
    select itm1;

这将为您提供列2中不存在的Coll1中的所有项目。这比任何时候使用contains都快