2017-07-17 82 views
0

我想找到一種方法,在if語句之後退出datareader,以便我可以在else語句中執行插入查詢。有沒有辦法做到這一點?在else之前退出datareader之前,在if-else語句中

我收到dr仍然打開的錯誤,因此無法執行下面的查詢。

sVendorDetails.VendorID = insertcmd.ExecuteNonQuery(); 

下面是代碼:

public class VendorDetails 
{ 
    int _VendorID; 
    string _VendorName; 

    public int VendorID 
    { 
     set { _VendorID = value; } 
     get { return _VendorID; } 
    } 

    public string VendorName 
    { 
     set { _VendorName = value; } 
     get { return _VendorName; } 
    } 
} 

public VendorDetails VendorCheck(string sVendorName) 
{ 
    SqlCommand cmd = new SqlCommand("dbo.usp_GetVendorByVendorName", myConnection); 
    cmd.CommandType = CommandType.StoredProcedure; 
    cmd.Parameters.Add(new SqlParameter("@VendorName", SqlDbType.VarChar)); 
    cmd.Parameters["@VendorName"].Value = sVendorName; 
    VendorDetails sVendorDetails = null; 

    try 
    { 
     myConnection.Open(); 
     SqlDataReader dr = cmd.ExecuteReader(); 
     if (dr.HasRows) 
     { 
      while (dr.Read()) 
      { 
       sVendorDetails = new VendorDetails(); 
       sVendorDetails.VendorID = ((int)dr["VendorID"]); 
       sVendorDetails.VendorName = ((string)dr["VendorName"]).ToUpper().Trim(); 
      } 
     } 
     else if (dr.HasRows!= true) 
     { 
      ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('VendorName:" + sVendorName + " not found. Inserting Vendor details into Vendor and Invoice table.')", true); 
      SqlCommand insertcmd = new SqlCommand("dbo.InsertVendorName", myConnection); 
      insertcmd.CommandType = CommandType.StoredProcedure; 
      insertcmd.Parameters.Add(new SqlParameter("@VendorName", SqlDbType.VarChar)); 
      insertcmd.Parameters["@VendorName"].Value = sVendorName; 
      sVendorDetails = new VendorDetails(); 
      sVendorDetails.VendorID = insertcmd.ExecuteNonQuery(); 
      sVendorDetails.VendorName = sVendorName; 
     } 

     dr.Close(); 
     return sVendorDetails; 

     } 
     catch (SqlException err) 
     { 
      throw new ApplicationException("DB usp_GetVendorByVendorName Error: " + err.Message); 
     } 

     finally 
     { 
      myConnection.Close(); 
     } 
    } 
+0

https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.close%28v=vs.110 %29.aspx?f = 255&MSPPError = -2147217396 –

+4

這就是爲什麼您應該始終使用['using'](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement)語句。 –

+2

'if(dr.HasRows){} else if(dr.HasRows!= true){}'第二個if塊沒有意義。 'if(dr.HasRows){} else {}'完成同樣的事情。 – Flater

回答

0

您需要重用連接之前關閉您的DataReader的/處置,因爲它仍在使用。

也許這樣?

var readerHasRows = false; 

using (var dr = cmd.ExecuteReader()) 
{ 
    readerHasRows = dr.HasRows; 

    if(readerHasRows) 
    { 
     while (dr.Read()) 
     { 
      sVendorDetails = new VendorDetails(); 
      sVendorDetails.VendorID = ((int)dr["VendorID"]); 
      sVendorDetails.VendorName = ((string)dr["VendorName"]).ToUpper().Trim(); 
     } 
    } 
} 

if(!readerHasRows) 
{ 
    ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('VendorName:" + sVendorName + " not found. Inserting Vendor details into Vendor and Invoice table.')", true); 
    SqlCommand insertcmd = new SqlCommand("dbo.InsertVendorName", myConnection); 
    insertcmd.CommandType = CommandType.StoredProcedure; 
    insertcmd.Parameters.Add(new SqlParameter("@VendorName", SqlDbType.VarChar)); 
    insertcmd.Parameters["@VendorName"].Value = sVendorName; 
    sVendorDetails = new VendorDetails(); 
    VendorDetails.VendorID = insertcmd.ExecuteNonQuery(); 
    sVendorDetails.VendorName = sVendorName; 
} 
+0

感謝Josh。這工作。 –

0

有幾件事情我想提一提

  1. 你的主要問題是,你不關閉你的DataReader。您可以使用using聲明
  2. 您不需要明確地打開和關閉SqlConnectionSqlCommand對象將根據需要執行此操作。
  3. 您不需要檢查if (dr.HasRows),然後再檢查while (dr.Read())。此外,您不需要循環僅拾取一行數據。
  4. 理想情況下,我會把「Fetch」部分放在一個單獨的函數中,並將「插入」放在一個單獨的函數中,這樣函數就會保持小而且可重用。
  5. 你的模式是多餘的if (flag) {TakeAction();}否則,如果(標誌!){TakeAction2();} . Every time the code hits the其他, it will also hit the如果(標誌!)`
  6. sVendorDetails.VendorID = insertcmd.ExecuteNonQuery();行看起來可疑。如果您的存儲過程返回VendorId,那麼您應該使用ExecuteScalar。目前它只是在所有情況下儲存1,因爲您大概會插入一行。
  7. 創建自定義ApplicationException時,不要丟棄原始SqlException。上游系統可能想知道比您傳遞的更多細節。一起將它作爲InnerException
  8. 我也改變了一些文體方面:
    1. 變量名稱更改爲更常用camelCase,而不是使用不當Hungarian NotationsVendorDetails而不是oVendorDetails
    2. 佈雷斯在ķ& [R風格
    3. 使用var時,右側是new聲明
    4. 使用對象初始化,而不是創造+分配

下面是代碼

public VendorDetails VendorCheck(string vendorName, SqlConnection myConnection) { 
    try { 
     return GetVendor(vendorName, myConnection) ?? InsertVendor(vendorName, myConnection); 
    } catch (SqlException err) { 
     throw new ApplicationException("DB usp_GetVendorByVendorName Error: " + err.Message, err); 
    } 
} 

VendorDetails GetVendor(string vendorName, SqlConnection myConnection) { 
    using (var cmd = new SqlCommand("dbo.usp_GetVendorByVendorName", myConnection)) { 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add(new SqlParameter("@VendorName", SqlDbType.VarChar)); 
     cmd.Parameters["@VendorName"].Value = vendorName; 

     using (SqlDataReader dr = cmd.ExecuteReader()) { 
      ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('VendorName:" + vendorName + " not found. Inserting Vendor details into Vendor and Invoice table.')", true); // TODO: Does this really belong here!?!? 
      if (dr.Read()) { 
       return new VendorDetails { 
        VendorID = ((int)dr["VendorID"]), 
        VendorName = ((string)dr["VendorName"]).ToUpper().Trim() 
       }; 
      } 
     } 
    } 

    return null; 
} 

VendorDetails InsertVendor(string vendorName, SqlConnection myConnection) { 
    using (var insertcmd = new SqlCommand("dbo.InsertVendorName", myConnection)) { 
     insertcmd.CommandType = CommandType.StoredProcedure; 
     insertcmd.Parameters.Add(new SqlParameter("@VendorName", SqlDbType.VarChar)); 
     insertcmd.Parameters["@VendorName"].Value = vendorName; 
     return new VendorDetails { 
      VendorID = (int)insertcmd.ExecuteScalar(), 
      VendorName = vendorName 
     }; 
    } 
} 
相關問題