代码之家  ›  专栏  ›  技术社区  ›  markzzz

如何优化此创建/更新/删除比较?

  •  1
  • markzzz  · 技术社区  · 6 年前

    我和EF 6在一起。

    我在数据库中有一个当前项目的列表,我用以下方法检索:

    ae_alignedPartners_olds = ctx.AE_AlignedPartners.AsNoTracking().ToList(); // list of List<AE_AlignedPartners>
    

    然后,我从JSON中重试相同的对象,方法是:

    ae_alignedPartners_news = GetJSONListObjects(); // list of List<AE_AlignedPartners>
    

    比我做一些比较(看看我需要更新哪些内容,哪些内容需要删除,哪些内容需要创建)。这就是当前的代码:

    // intersection
    var IDSIntersections = (from itemNew in ae_alignedPartners_news
                            join itemOld in ae_alignedPartners_olds on itemNew.ObjectID equals itemOld.ObjectID
                            select itemNew).Select(p => p.ObjectID).ToList();
    
    // to update
    IList<AE_AlignedPartners> ae_alignedPartners_toUpdate = new List<AE_AlignedPartners>();
    foreach (var item in IDSIntersections)
    {
        var itemOld = ae_alignedPartners_olds.First(p => p.ObjectID == item);
        var itemNew = ae_alignedPartners_news.First(p => p.ObjectID == item);
    
        if (itemOld.Field1 != itemNew.Field1 ||
            itemOld.Field2 != itemNew.Field2 ||
            itemOld.Field3 != itemNew.Field3 ||
            itemOld.Field4 != itemNew.Field4 ||
            itemOld.Field5 != itemNew.Field5 ||
            itemOld.Field6 != itemNew.Field6 ||
            itemOld.Field7 != itemNew.Field7 ||
            itemOld.Field8 != itemNew.Field8 ||
            itemOld.Field9 != itemNew.Field9)
        {
            itemOld.Field1 = itemNew.Field1;
            itemOld.Field2 = itemNew.Field2;
            itemOld.Field3 = itemNew.Field3;
            itemOld.Field4 = itemNew.Field4;
            itemOld.Field5 = itemNew.Field5;
            itemOld.Field6 = itemNew.Field6;
            itemOld.Field7 = itemNew.Field7;
            itemOld.Field8 = itemNew.Field8;
            itemOld.Field9 = itemNew.Field9;
    
            ae_alignedPartners_toUpdate.Add(itemOld);
        }
    }
    
    // to create
    IList<AE_AlignedPartners> ae_alignedPartners_toCreate = ae_alignedPartners_news.Where(p => !IDSIntersections.Contains(p.ObjectID)).ToList();
    
    // to delete
    IList<AE_AlignedPartners> ae_alignedPartners_toDelete = ae_alignedPartners_olds.Where(p => !IDSIntersections.Contains(p.ObjectID)).ToList();
    

    速度快到1000条记录。超过50K,速度变慢了。

    你建议如何提高整体水平?

    1 回复  |  直到 6 年前
        1
  •  1
  •   usr    6 年前

    如果您想知道什么是慢的,我建议您进行分析,或者简单地暂停调试器10次以查看它最常停止的位置(您可以使用现有的代码来尝试)。但在这里,我可以立即发现问题:

    var itemOld = ae_alignedPartners_olds.First(p => p.ObjectID == item);
    var itemNew = ae_alignedPartners_news.First(p => p.ObjectID == item);
    

    这是扫描整个列表,即O(N)。与外环一起,它变成O(n^2)。

    最好的解决方案是重新构造查询,这样就不需要进行这些查找。在我看来,联接已经输出了您需要的对象。

    但是您也可以使用哈希表来加速查找。

    var dict_ae_alignedPartners_olds = ae_alignedPartners_olds.ToDictionary(p => p.ObjectID);
    var dict_ae_alignedPartners_news = ae_alignedPartners_news.ToDictionary(p => p.ObjectID);
    
    foreach (var item in IDSIntersections)
    {
        var itemOld = dict_ae_alignedPartners_olds[item];
        var itemNew = dict_ae_alignedPartners_news[item];
        //...
    }