C# LINQ 与两个不同数据集上的条件 where 子句连接

Posted

技术标签:

【中文标题】C# LINQ 与两个不同数据集上的条件 where 子句连接【英文标题】:C# LINQ join with conditional where clause on two different data sets 【发布时间】:2016-06-01 15:14:30 【问题描述】:

我有两个要比较数据的集合。我可以通过 id 加入这两个集合。我需要一个 where 子句,它返回一个数据列表,其中集合 B 中的某些项目在集合 A 中没有找到

公共类合约 公共字符串 ContractId 获取;放; 公共 IList InvoiceList 获取;放; 公共类发票 公共 int InvoiceNumber 获取;放; 公共类 PaymentRequest 公共 IList 合同 获取;放; 公共类合同清单 公共字符串 ContractId 获取;放; 公共 IList 发票 获取;放; 公共类 InvoiceList 公共 int InvoiceNumber 获取;放;

到目前为止,我有以下内容,但无法完全理解 where 子句。

变种查询 = ( 来自请求( 来自 paymentRequest.Contracts 中的合同 来自合同中的发票。发票 选择新的合同,发票) 加入有效( 来自有效合同中的合同 选择新的合同) 在 new request.contract.ContractId 上等于 new valid.contract.ContractId 在哪里 !( // 获取请求数据集中不在有效数据集中的发票号码列表 ) 选择“合同 ID:” + request.contract.ContractId + ", 发票编号:" + request.invoice.InvoiceNumber ).ToList();

感谢任何帮助。

【问题讨论】:

你能用“商业”术语来表述你的问题吗?我根本看不到你想做什么。 (如果您使用合同或发票等术语而不是集合 A 和 B,这会有所帮助) 您的代码甚至无法编译(甚至忽略位置)。如果有,那将非常有用。 【参考方案1】:
var collectionAIds = new HashSet<int>(collectionA.Select(colAItem => colAItem.Id));
var itemsInCollectionBNotInCollectionA = collectionB.Where(colBItem => 
                                             !collectionAIds.Contains(colBItem.Id));

基本上,我们想获取集合 A 中的 Id,然后选择集合 B 中的所有项目,而不是 A 的 id 列表中的所有项目。

HashSet 是可选的。如果您不使用该变量,它只是避免重复的 O(n) 查找。

附言我假设 int,作为 id 的类型。使用 id 的数据类型作为 Hashset。

【讨论】:

【参考方案2】:

使用contains 获得的性能低于提醒常规 Sql 查询的东西。这样会更好

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

这将为您提供 Coll1 中 Coll2 中不存在的所有项目。这将比任何时候使用Contains 更快

【讨论】:

【参考方案3】:

在我看来,您的查询应该是这样的:

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();

【讨论】:

以上是关于C# LINQ 与两个不同数据集上的条件 where 子句连接的主要内容,如果未能解决你的问题,请参考以下文章

在比较器包含 DbNull 的强类型数据集上的 Linq JOIN 抛出异常

一LINQ简介

C# 使用带有 where 子句的 Linq 查询作为 dataTable 上的变量

基于条件的 2 个大型数据集上的模糊模糊字符串匹配 - python

如何关联不同 dbml 图上的 Linq-To-Sql 对象?

c# Linq 方法不符合我设置的条件之一