C# 优化存储过程循环
我有一个c#应用程序,我在c#中调用一个存储过程,我将一个list对象传递给该过程,它对记录运行验证。然而,处理大量记录的过程非常缓慢,是否有更好的方法来实现这一点。请看下面我的代码C# 优化存储过程循环,c#,linq,C#,Linq,我有一个c#应用程序,我在c#中调用一个存储过程,我将一个list对象传递给该过程,它对记录运行验证。然而,处理大量记录的过程非常缓慢,是否有更好的方法来实现这一点。请看下面我的代码 using (SqlConnection conn = new SqlConnection(sqlConnection)) { try { foreach (var claim in supplierClaimsData) { SqlComma
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,但我不知道如何优化此代码,希望您能提供帮助。我发现存储过程会对每个记录调用多次,这会导致时间延迟。因此,建议通过XML或Table type变量将“supplierClaimsData”列表/数组作为一个整体传递给过程,并让过程为后续输入记录返回一个表。然后对每个结果表执行while循环,这样会更快 链接中定义了将表传递给过程的示例之一。
因为您在使用部分,所以不必明确地关闭连接。优化可以是使用线程池或简单的Parallel.foreacher对存储过程调用进行多线程处理,并获得更好的性能,从而获得storedproc的代码,并制作另一个直接从源表读取的版本,等等。我没有权限修改过程,因为它是由BI团队构建的,他们构建它是为了允许过程采用两个参数,索赔发票和金额,我的列表由带有发票和金额的项目组成。有没有一种方法可以在不修改过程的情况下实现这一点?在这种情况下,在foreach循环之前泛化SQLCommand和过程声明,并且不要关闭SQLconnection。在foreach循环之后关闭它。在datatable中收集每次迭代的返回结果,并重新构造while循环逻辑以适应datatable。@papi获取过程的代码并创建一个新过程(最佳)。或者在另一个程序中包装该程序(不太好)