【问题标题】:Linq - How to check if an object exists in databaseLinq - 如何检查数据库中是否存在对象
【发布时间】:2011-03-27 22:58:43
【问题描述】:

我有一个内存对象列表。我想检查每个对象是否存在于数据库中,如果不存在,则将该对象的 bool 属性设置为 true。

对象

class Part
    {
        public bool NewPart { get; set; }
        public string PartNumber { get; set; }
        public string Revision { get; set; }
        public string Description { get; set; }
    }

List 包含部分的集合。对于每个部件,如果它存在于数据库中,则 NewPart 应设置为 FALSE,否则为 TRUE。我正在寻找最有效的方法来做到这一点,因为可能有数百个部分,所以我认为为每个部分运行 SQL 查询可能不是最有效的方法。

对实现这一目标的最佳方法的想法表示赞赏。

【问题讨论】:

  • Part 表的主键是什么?零件号?

标签: linq


【解决方案1】:

这取决于您使用的是哪个 ORM,但使用 Linq2Sql 您可以使用如下查询:

var query = from p in db.parts
            where myList.Contains(p.PartNumber)
            select p.PartNumber;

然后您可以使用返回的IEnumerable 来设置您的 newPart 字段

作为替代方案,如果您的最终目标是执行 Upsert 类型操作,请查看此问题及其答案 Insert Update stored proc on SQL Server(需要 SQL 级别实现,而不是 linq)

【讨论】:

    【解决方案2】:

    以下只会命中数据库一次。

       var myList = (from r in parts select r.PartNumber).ToList();
    
        var existingParts = (from r in dc.Parts
           where myList.Contains(r.PartNumber) select r.PartNumber).ToList();
    
        foreach(var r in parts)
             r.NewPart = existingParts.Contains(r.PartNumber);
    

    注意,生成的 sql 很可能类似于

    SELECT PartNumber
    FROM Parts Where PartNumber in (@p0, @p1, @p2, @p3 .... )
    

    所以如果零件清单有一百个左右,这应该可以工作,但如果超过 2100 个,则不行。

    【讨论】:

      【解决方案3】:

      这是最有效的方法取决于实际数据的情况之一。

      第一个从数据库中获取所有partNums:

      HashSet<int> partNums = new HashSet<int>(from p in GetTable<DBPart> select p.PartNumber);
      foreach(var p in parts)
        p.NewPart = partNums.Contains(p.PartNumber);
      

      第二个用相关的partNumbers查询数据库:

      HashSet<int> partNums = new HashSet<int>(
        from p in GetTable<DBPart> where (from mp in parts select mp.PartNumber).Contains(p.PartNumber) select p.PartNumber);
      foreach(var p in parts)
        p.NewPart = partNums.Contains(p.PartNumber);
      

      前者在数据库中一定数量的行之上效率更高,而在它之上效率较低,因为后者需要更长的时间来构建更复杂的查询,但前者返回所有内容。

      另一个因素是预期命中的百分比。如果这个数字相对较低(即列表中只有少数部分会在数据库中),那么这样做可能更有效:

      Dictionary<int, Part> dict = partsSource.ToDictionary(p => p.PartNumber, p);
      foreach(int pn in 
        from p in GetTable<DBPart> where (from kv in dict select kv.Key).Contains(p.PartNumber) select p.PartNumber);
        dict[pn].NewPart = true;
      

      其中partsSource 是首先获取列表parts 的方法,这里不是获取列表,而是获取字典,这样可以更有效地检索我们想要的内容。但是,无论如何我们都将获得parts 作为一个列表,那么我们在这里就无法真正获得收益,因为我们首先在构建字典时花费了比遍历列表更多的精力。

      【讨论】:

        猜你喜欢
        • 2016-10-24
        • 2013-03-10
        • 1970-01-01
        • 2015-11-11
        • 1970-01-01
        • 1970-01-01
        • 2017-11-22
        • 2021-09-12
        • 1970-01-01
        相关资源
        最近更新 更多