优化存储过程循环

时间:2016-07-20 06:43:20

标签: c# linq

我有一个c#应用程序,我在C#中调用存储过程,我将一个列表对象传递给该过程,并对记录运行验证。然而,处理大量记录的速度非常慢,是否有更好的方法来实现这一目标。请参阅下面的代码

using (SqlConnection conn = new SqlConnection(sqlConnection))
{
    try
    {
        foreach (var claim in supplierClaimsData)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandTimeout = 60;
            cmd.CommandText = "CRM.Supplier_Claim_Upload";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@Invoice", SqlDbType.NVarChar).Value = claim.Line_Number;
            cmd.Parameters.Add("@Amount", SqlDbType.Decimal).Value = claim.Total_Claim;
            cmd.Connection = conn;

            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                claim.ST_Key = reader.GetString(reader.GetOrdinal("ST_Key"));
                claim.Error_1 = reader.GetString(reader.GetOrdinal("Error1"));

                string lineNumberDoesNotExist = "Error: Invoice line number does not exist";
                if (claim.Error_1.StartsWith(lineNumberDoesNotExist))
                {
                    continue;
                }

                claim.Warning = reader.GetString(reader.GetOrdinal("Warning"));
                claim.Error_2 = reader.GetString(reader.GetOrdinal("Error2"));
                string warningCleanInclusion = "Warning";

                if (claim.ST_Key != null && string.IsNullOrEmpty(claim.Warning) && string.IsNullOrEmpty(claim.Error_1) && string.IsNullOrEmpty(claim.Error_2))
                {
                    var existingClaimCount = db.GPClaimsReadyToImports.Count(a => a.ST_Key == claim.ST_Key && a.CleanSupplierClaimSessionID == claim.CleanSupplierClaimsUploadSessionID);
                    if (existingClaimCount == 0)

                        db.GPClaimsReadyToImports.Add(new GPClaimsReadyToImport
                        {
                            Id = claim.Id,
                            ST_Key = claim.ST_Key,
                            Warning = claim.Warning,
                            Action = claim.Action,
                            Claim_Reference = claim.ClaimReference,
                            Currency = claim.Currency,
                            Error_1 = claim.Error_1,
                            Error_2 = claim.Error_2,
                            Line_Number = claim.Line_Number,
                            Total_Claim = claim.Total_Claim,
                            Domain_Username = domainNameOfficial.ToString(),//claim.Domain_Username,
                            DateCreated = DateTime.Now,
                            ImportFlag = true,
                            ReadyForImport = true,
                            CleanSupplierClaimSessionID = sessionIdentifier

                        });
                    db.SaveChanges();
                }
            }

            foreach (CleanSupplierClaim saveToDBClaim in supplierClaimsData)
            {
                db.CleanSupplierClaims.Attach(saveToDBClaim);

                var entry = db.Entry(saveToDBClaim);
                entry.Property(aa => aa.Line_Number).IsModified = true;
                entry.Property(aa => aa.Total_Claim).IsModified = true;
                entry.Property(aa => aa.Currency).IsModified = true;
                entry.Property(aa => aa.ClaimReference).IsModified = true;
                entry.Property(aa => aa.Action).IsModified = true;
                entry.Property(aa => aa.Domain_Username).IsModified = true;
                entry.Property(aa => aa.Error_1).IsModified = true;
                entry.Property(aa => aa.Error_2).IsModified = true;
                entry.Property(aa => aa.Warning).IsModified = true;
                entry.Property(aa => aa.ImportFlag).IsModified = true;
                entry.Property(aa => aa.ReadyForImport).IsModified = true;
                db.Entry(saveToDBClaim).State = System.Data.Entity.EntityState.Modified;
                db.SaveChanges();
            }

            conn.Close();
        }
    }
}

我想知道是否有一种方法可以排除在循环中调用proc,但不知道如何优化此代码,任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

我看到每个记录多次调用存储过程,这会导致时间延迟。因此建议通过XML或Table类型变量将“supplierClaimsData”List / Array传递给整个过程,并让过程为后续输入记录返回一个表。然后为每个结果表执行while循环,这将更快......

在链接中定义了将表传递给过程的示例之一。 How to pass User Defined Table Type as Stored Procedured parameter in C#