2016-07-20 5 views
-1

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(); 
     } 
    } 
} 

아래에있는 내 코드를 참조하십시오, 어떤 도움을 이해할 수있을 것이다.

+0

사용중인 섹션에 있으므로 연결을 명확히 할 필요가 없습니다. –

+0

스레드 풀 또는 간단한 Parallel.ForEach –

+0

을 사용하는 저장 프로 시저 호출의 멀티 스레딩이 최적화 될 수 있으며 storedproc의 코드를 얻고 소스 테이블에서 직접 읽는 다른 버전을 만드는 것이 더 나은 성능 향상을 얻을 수 있습니다. – montewhizdoh

답변

1

각 레코드에 대해 저장 프로 시저가 여러 번 호출되므로 시간 지연이 발생합니다. 따라서 "supplierClaimsData"List/Array를 XML 또는 테이블 유형 변수를 통해 전체 프로 시저에 전달하고 프로 시저가 후속 입력 레코드 용 테이블을 반환하도록하는 것이 좋습니다. 그런 다음 각 결과 테이블에 대한 while 루프를 수행하면 더 빠를 것입니다 ...

프로 시저에 테이블을 전달하는 예제 중 하나가 링크에 정의되어 있습니다. How to pass User Defined Table Type as Stored Procedured parameter in C#

+0

BI 팀이 구축 한대로 proc를 수정할 수있는 권한이 없습니다. proc가 두 개의 매개 변수를 사용하고 송장 및 금액을 청구 할 수 있도록 작성했으며, 내 목록은 청구서와 금액이있는 항목으로 구성됩니다. 프로 시저를 수정하지 않고도이를 수행 할 수있는 방법이 있습니까? – Papi

+1

그런 경우 foreach 루프 전에 SQLCommand 및 프로 시저 선언을 일반화하고 SQL 연결을 닫지 마십시오. foreach 루프가 끝나면 닫습니다. 각 반복의 반환 된 결과를 데이터 테이블에 수집하고 while 루프 논리를 재구성하여 데이터 테이블을 수용합니다. –

+0

@papi 프로 시저에 대한 코드를 가져 와서 새 프로 시저를 만듭니다 (최선). 또는 다른 프로 시저에서 프로 시저를 래핑 (좋지 않음) – montewhizdoh