c# 踩坑之List<T>.Contains 方法不适用于比较两个字典对象

周六加班测试"欢乐"多。。。。。。

平时写代码用习惯了list.contains(),好像对它没有太多想法,毕竟也没出过bug。咦,今天怎么突然失效了???

ini 复制代码
                    if (matnrRequest.TableNameList.Contains("T_MAKT"))
                    {
                        DataTable T_MAKT = dsSap.Tables["T_MAKT"];

                        //取出当前存在的物料号&语言代码
                        List<Dictionary<string, string>> RawDataList = new List<Dictionary<string, string>>();
 
                        var query = from p in context.SAP_MAKT
                                     select new
                                     {
                                         p.MATNR,
                                         p.SPRAS
                                     };
                         foreach (var item in query)
                         {
                             Dictionary<string, string> RawData = new Dictionary<string, string>();
                             RawData.Add("MATNR", item.MATNR);
                             RawData.Add("SPRAS", item.SPRAS);
                             RawDataList.Add(RawData);
                         }

 
                         List<SAP_MAKT> sAP_MAKTs = new Tool_Reflection<SAP_MAKT>().ConvertDataTableToList(T_MAKT);
                         if (sAP_MAKTs == null || sAP_MAKTs.Count == 0)
                         {
                             sAP_MAKTs = new List<SAP_MAKT>();
                         }
 
                         sAP_MAKTs.ForEach(t =>
                         {
                             t.CREATETIME = nowDate;
 
                            Dictionary<string, string> data = new Dictionary<string, string>();
                             data.Add("MATNR", t.MATNR);
                             data.Add("SPRAS", t.SPRAS);
 
                             //如果存在,则更新
                             if (RawDataList.Contains(data))
                             {
                                 var q = from p in context.SAP_MAKT
                                         where p.MATNR.Equals(t.MATNR) && p.SPRAS.Equals(t.SPRAS)
                                         select p;
 
                                 foreach (var p in q)
                                 {
                                     p.MAKTX = t.MAKTX;
                                     p.CREATETIME = t.CREATETIME;
                                 }
 
                             }
                             else
                             {
                                 context.SAP_MAKT.Add(t);
                             }
                             
                            
                         });
                        
                         context.SaveChanges();

                     }
                     

上述代码需要实现的功能就是:存在则update,不存在则insert。

测试时发现存在也insert,问题出在哪里?

经过对list.contains()的研究得知:List<T>.Contains 方法默认使用对象的 Equals 方法来比较列表中的每个元素与给定的对象是否相等。对于字典类型,这意味着它会比较两个字典对象的引用,而不是它们的值。

在上述代码中,RawDataList 包含的是字典的列表,而 data 也是一个字典。即使 data 的键值对与 RawDataList 中某个字典的键值对相同,Contains 方法也会返回 false,因为它比较的是两个不同的字典对象的引用。

为了解决这个问题,我们需要自定义比较逻辑来检查 RawDataList 中是否存在具有相同键值对的字典。也可以通过以下方式来实现:

  1. 遍历 RawDataList 并比较每个字典的键值对。
  2. 使用 LINQ 的 Any 方法来简化这个过程。

下面是一个使用 LINQ 的 Any 方法来检查 data 是否存在于 RawDataList 中的示例:

arduino 复制代码
// 检查是否存在具有相同MATNR和SPRAS的字典
bool exists = RawDataList.Any(rd => rd["MATNR"] == data["MATNR"] && rd["SPRAS"] == data["SPRAS"]);
if (exists)
{
   // 如果存在,执行更新操作
}
else
{
   // 如果不存在,执行插入操作
}

这段代码会检查 RawDataList 中是否有任何字典的 MATNRSPRAS 键的值与 data 字典中的相应值相匹配。如果找到匹配的字典,exists 将为 true,然后你可以在 if 块中执行更新操作;如果没有找到匹配的字典,exists 将为 false,你可以在 else 块中执行插入操作。

相关推荐
没有bug.的程序员4 分钟前
Spring Cloud Sentinel:熔断降级规则配置与分布式流量防线实战终极指南
java·分布式·后端·spring cloud·sentinel·熔断规则·分布式流量防线
JP-Destiny5 分钟前
后端-RabbitMQ
后端·消息队列·rabbitmq·java-rabbitmq
李慕婉学姐8 分钟前
【开题答辩过程】以《基于SpringBoot Vue的校园后勤管理系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
vue.js·spring boot·后端
咖啡啡不加糖13 分钟前
Arthas 使用指南:Java 应用诊断利器
java·spring boot·后端
J_liaty14 分钟前
SpringBoot整合Canal实现数据库实时同步
数据库·spring boot·后端·canal
lead520lyq14 分钟前
Golang Grpc接口调用实现账号密码认证
开发语言·后端·golang
JaguarJack17 分钟前
Laravel AI SDK 在 Laracon India 2026 首次亮相
后端·php·laravel
bjxiaxueliang2 小时前
一文掌握SpringBoot:HTTP服务开发从入门到部署
spring boot·后端·http
野犬寒鸦15 小时前
从零起步学习并发编程 || 第一章:初步认识进程与线程
java·服务器·后端·学习
我爱娃哈哈15 小时前
SpringBoot + Flowable + 自定义节点:可视化工作流引擎,支持请假、报销、审批全场景
java·spring boot·后端