【问题标题】:how can I Optimize this foreach我怎样才能优化这个foreach
【发布时间】:2020-04-05 08:34:08
【问题描述】:
        public int SetNumber(FinancialEntities db, bool Redirected = false)
        {
            db = new FinancialEntities();
            List<Document> ds = db.Documents.Where(d => DbFunctions.TruncateTime(d.Date) > DbFunctions.TruncateTime(Date) && d.UnitID == UnitID).ToList();
            ds.Remove(this);
            ds = ds.OrderBy(d => d.Date).ToList();
            if (ds.Count > 0)
            {
                Number = ds.FirstOrDefault().Number;
                int tn = (int)Number;
                foreach (var item in ds)
                {
                    tn++;
                    if (item.Number != tn)
                    {
                        item.Number = tn;
                        db.Entry(item).State = System.Data.Entity.EntityState.Modified;
                    }
                }
                db.SaveChanges();
            }
            else
            {
                Number = db.Documents.Where(d => d.UnitID == UnitID).Count() > 0 ? db.Documents.Where(d => d.UnitID == UnitID).Max(d => d.Number) + 1 : 1;
            }
            List<int?> nums = db.Documents.Where(d => d.UnitID == UnitID).Select(d => d.Number).ToList();
            int nc = nums.Count();
            int ndc = nums.Distinct().Count();
            if (nums.Distinct().Count() != nums.Count() && Redirected == false)
            {
                if (ds.Count() == 0)
                    ds = db.Documents.Where(d => d.UnitID == UnitID).ToList();
                ds.First().SetNumber(db, true);
            }
            return (int)Number;
        }

这是一种将数字放在日期开头并在该日期之后修复其余条目的方法。遍历条目需要很长时间,并导致很多问题。我该如何优化呢?

【问题讨论】:

  • 您是否对代码进行了概要分析或对各个部分进行了计时?是什么让您认为foreach 是具体原因?我假设您的意思是SaveChanges 附近的foreach?我们在谈论多少数据?还有多少时间?如果您将其分成两个循环(纯粹出于计时目的),在第二个循环中使用db.Entry(item).State =...,会发生什么情况?也许大部分时间都在里面?等等.... 还是 SaveChanges 需要时间?是否可以通过 SQL 将更新写入数据库服务器中的批量操作以避免所有这些?
  • 对不起,您不只是增加所有日期字段的日期大于this 的日期字段的记录的数字字段吗?这效率不高。为什么不发布您的数据库和类结构并让我们提供帮助?
  • 为什么一开始要打两次ToList?这是一个 O(n) 操作,在您的代码中不需要。
  • @MarcGravell 你能指出我在数据库中作为批量操作的方向吗?
  • @MarcGravell 问题是被迭代的数据的大小。一次超过 2000 条记录,如果存在不匹配或重复值,则需要遍历所有记录以确保数字有序且正确

标签: c# loops optimization foreach


【解决方案1】:

您可以尝试从数据库中删除大量读取并在内存中执行所有操作。

类似这样的:

 public int SetNumber(FinancialEntities db, bool Redirected = false)
    {
        db = new FinancialEntities();
        var docs = db.Documents.Where(d => d.UnitID == UnitID).ToList();
        var ds = docs.Where(d => d.Date > Date).ToList();
        ds.Remove(this);
        ds = ds.OrderBy(d => d.Date).ToList();
        if (ds.Count > 0)
        {
            Number = ds.FirstOrDefault().Number;
            int tn = (int)Number;
            foreach (var item in ds)
            {
                tn++;
                if (item.Number != tn)
                {
                    item.Number = tn;
                    db.Entry(item).State = System.Data.Entity.EntityState.Modified;
                }
            }
            db.SaveChanges();
        }
        else
        {
            Number = docs.Count > 0 ? docs.Max(d => d.Number) + 1 : 1;
        }

        List<int?> nums = docs.Select(d => d.Number).ToList();
        int nc = nums.Count;
        int ndc = nums.Distinct().Count();
        if (ndc != nc && Redirected == false)
        {
            if (ds.Count == 0)
                ds = docs.ToList();
            ds.First().SetNumber(db, true);
        }
        return (int)Number;
    }

【讨论】:

    猜你喜欢
    • 2021-04-30
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多