2014-01-16 22 views
0

對這個代碼片段的任何評論,使它更專業將很樂意接受。這就是爲什麼我打開這個話題。但主要關心的是這個;我需要傳遞商品ID,商店ID,並開始日期和結束日期以獲得銷售記錄。其中一個問題是由於SQL參數限制(2100),我無法發送超過2100個參數給語句。現在我試圖接收商店的記錄存儲(商店數量超過4000,也是商品數量)。但我找不到一個好的方法來做到這一點。什麼是從場景中獲取數據庫記錄的最佳方式,您必須通過列表,其中每個參數都有超過2000個參數?

任何一個花時間去幫助表示讚賞的人。

這是數據訪問:

public List<SalesList> ExecuteSales(List<string> items, int storeID, int W1,int W2,int vendorID,int retailerID) 
{ 
     SqlCommand command = new SqlCommand(); 

     string statement = "SELECT I.ITEM_NBR,I.ITEM_DESC1,I.ITEM_DESC2,I.VENDOR_STK_NBR,SUM(SA.POS_QTY) AS POS_QTY,SUM(SA.POS_SALES) AS POS_SALES " 
          + "FROM SALES_FTBL SA,ITEM_TBL I " 
         + "WHERE SA.RETAILER_ID=I.RETAILER_ID " 
         + "AND SA.RETAILER_ID = @RetailerID " 
         + "AND SA.VENDOR_NBR = @VendorID " 
         + "AND SA.STORE_NBR = @StoreID " 
         + "AND SA.ITEM_NBR=I.ITEM_NBR " 
         +"AND SA.ITEM_NBR IN ("; 

     command.Parameters.AddWithValue("@RetailerID", retailerID); 
     command.Parameters.AddWithValue("@VendorID",vendorID); 
     command.Parameters.AddWithValue("@StoreID", storeID); 

     for (int i = 0; i < items.Count; i++) 
     { 
      if (i > 0) 
      { 
       statement += ", "; 
      } 
      string paramStr = "@itemNo" + i; 
      statement += paramStr; 
      command.Parameters.Add(paramStr, System.Data.SqlDbType.Int); 
      command.Parameters[paramStr].Value = items[i]; 
     } 
     statement += ") "; 

     //statement += "AND STORE_NBR IN ("; 
     //for (int i = 0; i < stores.Count; i++) 
     //{ 
     // if (i > 0) 
     // { 
     //  statement += ", "; 
     // } 
     // string paramStr = "@storeNo" + i; 
     // statement += paramStr; 
     // command.Parameters.Add(paramStr, System.Data.SqlDbType.Int); 
     // command.Parameters[paramStr].Value = stores[i]; 
     //} 
     //statement += ") "; 

     statement += "AND WEEK IN ("; 
     for (int i = 0; i <1; i++) 
     { 
      if (i > 0) 
      { 
       statement += ", "; 
      } 
      string paramStr = "@W" + i; 
      statement += paramStr; 
      command.Parameters.Add(paramStr, System.Data.SqlDbType.Int); 
      command.Parameters[paramStr].Value = W1; 
     } 
     W1=W1+1; 
     for (int counter=W1; counter < W2;counter++) 
     { 
      if (counter > 0) 
      { 
       statement += ", "; 
      } 
      string paramStr = "@W" + counter; 
      statement += paramStr; 
      command.Parameters.Add(paramStr, System.Data.SqlDbType.Int); 
      command.Parameters[paramStr].Value = W1++; 
     } 

     statement += ") "; 

     statement += "GROUP BY I.ITEM_NBR,I.VENDOR_STK_NBR,I.ITEM_DESC1,I.ITEM_DESC2 Order By I.ITEM_DESC2 "; 

     command.CommandText = statement; 
     command.Connection = connection; 

     List<SalesList> sales = new List<SalesList>(); 
     SalesList sale; 
     string itemDescription; 
     string desc1; 
     string desc2; 
     int count = 0; 
     try 
     { 
      connection.Open(); 

      SqlDataReader reader = command.ExecuteReader(); 
      while (reader.Read()) 
      { 
       sale = new SalesList(); 

       sale.ItemNumber = Convert.ToInt32(reader["ITEM_NBR"].ToString().TrimEnd()); 

       if (reader["ITEM_DESC1"] != null) 
       { 
        desc1 = reader["ITEM_DESC1"].ToString().TrimEnd(); 
       } 
       else { desc1 = ""; } 

       if (reader["ITEM_DESC2"] != null) 
       { 
        desc2 = reader["ITEM_DESC2"].ToString().TrimEnd(); 
       } 
       else { desc2 = ""; } 

       if (!desc1.Equals(desc2) || !desc2.Equals(desc1)) 
       { itemDescription = desc1 + " " + desc2; } 
       else { itemDescription = desc2; } 

       sale.ItemDescription2 = itemDescription; 

       sale.PosQuantity = Convert.ToInt32(reader["POS_QTY"].ToString().TrimEnd()); 
       sale.VendorStockNumber = reader["VENDOR_STK_NBR"].ToString().TrimEnd(); 


       if (reader["POS_SALES"].ToString() != "") 
       { 
        sale.PosSales = Convert.ToDouble(reader["POS_SALES"].ToString().TrimEnd()); 
       } 
       else { sale.PosSales = 0; } 

       sales.Add(sale); 
      } 
     } 
     catch (SqlException se) 
     { 
      Debug.WriteLine("---------- DEBUG INFORMATION ----------"); 
      Debug.WriteLine(se.Message); 
      Debug.WriteLine("======================================="); 
      throw se; 
     } 
     finally 
     { 
      connection.Close(); 
     } 
     return sales; 
    } 

這是業務層:

private List<SalesList> ExecuteSales(List<string> items, List<string> stores, string date1, string date2, int vendorID, int retailerID) { 

     int W1 = CalculateWeek(date1); 
     int W2 = CalculateWeek(date2); 
     SalesListDL salesListDO = new SalesListDL(); 
     List<SalesList> sales = new List<SalesList>(); 
     List<SalesList> salesX = new List<SalesList>(); 

     for (int counter = 0; counter < stores.Count; counter++) 
     { 
       int storeID = Convert.ToInt32(stores[counter]); 

       salesX = salesListDO.ExecuteSales(items, storeID, W1, W2, vendorID, retailerID); 
       if (salesX.Count > 0) 
       { 
        foreach (SalesList saleX in salesX.ToList()) 
        { 
         int index = sales.FindIndex(item => item.ItemNumber == saleX.ItemNumber); 
         if (index > 0) 
         { 
          sales[index].PosQuantity = +saleX.PosQuantity; 
          sales[index].PosSales = +saleX.PosSales; 
          salesX.Remove(saleX); 
         } 
         else { sales.Add(saleX); } 
        } 
       } 
     } 

     return sales; 
    } 
+1

如果你想送**,很多paramters **,然後有一些**根本上可怕的錯誤**你設計!你沒有提及**你正在使用什麼具體的數據庫**,但是他們中的大多數都提供了對「基於列表」的值的某種支持,這不需要單獨設置2000多個參數....對於SQL Server ** 2008和更新版本**,請查看[表值參數](http://msdn.microsoft.com/zh-cn/library/bb675163%28v=vs.110%29)。aspx) –

+0

謝謝馬克,你絕對正確,這是一個可怕的錯誤。我正在使用Microsoft SQL Server 2008.除了「基於列表」的值之外,您是否有任何建議,我可以解決的任何編程邏輯。 – Davy

回答

1

表值參數是去,如果這確實是你需要處理這個議題的方式方法。

  • 首先,切換到存儲過程,因爲您使用的是SQL 2008或 以上的版本。
  • 其次,請閱讀using聲明處理您的 sql項目。

的僞數據層:

public List<SalesList> ExecuteSales(List<string> items, int storeID, int W1, int W2, int vendorID, int retailerID) 
{ 
    var sales = new List<SalesList>(); 
    var table = new DataTable(); 
    table.Columns.Add("ItemNumber"); 
    foreach (var item in items) 
    { 
     table.Rows.Add(item); 
    } 
    using (var connection = new SqlConnection("ConnectionString")) 
    { 
     connection.Open(); 
     using (var command = connection.CreateCommand()) 
     { 
      command.CommandType = CommandType.StoredProcedure; 
      command.CommandText = "cp_ExecuteSales"; 
      command.Parameters.AddWithValue("@RetailerID", retailerID); 
      command.Parameters.AddWithValue("@VendorID", vendorID); 
      command.Parameters.AddWithValue("@StoreID", storeID); 
      var tvp = new SqlParameter("@ItemIds", SqlDbType.Structured) 
      { 
       TypeName = "tvpItems", 
       Value = table 
      }; 
      command.Parameters.Add(tvp); 
      using (var reader = command.ExecuteReader()) 
      { 
       //DoWork 
      } 
     } 
    } 
    return sales; 
} 

創建TVP:

CREATE TYPE [dbo].[tvpItems] AS TABLE(
[ItemNumber] [int] NULL 

創建存儲過程:

CREATE PROCEDURE cp_ExecuteSales 
    @RetailerID VARCHAR(50), 
    @VendorID VARCHAR(50), 
    @StoreID VARCHAR(50), 
    @ItemIds tvpItems READONLY 
AS 
    SELECT I.ITEM_NBR 
      ,I.ITEM_DESC1 
      ,I.ITEM_DESC2 
      ,I.VENDOR_STK_NBR 
      ,SUM(SA.POS_QTY) AS POS_QTY 
      ,SUM(SA.POS_SALES) AS POS_SALES 
    FROM SALES_FTBL SA 
     INNER JOIN ITEM_TBL I ON SA.RETAILER_ID = I.RETAILER_ID 
      AND SA.ITEM_NBR = I.ITEM_NBR 
     INNER JOIN @ItemIds ID ON SA.ITEM_NBR = ID.ItemNumber 
    WHERE SA.RETAILER_ID=I.RETAILER_ID 
     AND SA.RETAILER_ID = @RetailerID 
     AND SA.VENDOR_NBR = @VendorID 
     AND SA.STORE_NBR = @StoreID 
     AND SA.ITEM_NBR=I.ITEM_NBR 

如果您需要添加第二組號碼參數,則可以將多個不同類型的參數傳遞給數據庫。過去,我們已經創建了幾種通用類型來支持不同的數據類型列表,而不必管理大量的表類型。

CREATE TYPE [dbo].[IntList] AS TABLE(
    [Value] [Int] NULL 
) 

重要的事情要記住:

  • 參數類型爲TVP必須SqlDbType.Structured
  • TypeName的參數必須與表值參數 類型名稱相匹配。
  • 在存儲過程中的表值參數參數必須 聲明爲READONLY
+0

謝謝巴里,我還沒有嘗試,但是你提高了我的視野。我相信它會解決我的問題。另一方面,你會在這種情況下做什麼,需要什麼樣的設計/架構? – Davy

+1

如果這純粹是一份銷售報告,那麼在一段時間間隔內逐一詢問每件商品並在客戶端上過濾而不是按商品標識進行過濾可能更有價值。 –

相關問題