在if-else语句之前退出datareader

时间:2017-07-17 15:08:04

标签: c#

我想找到一种方法在if语句之后退出datareader,这样我就可以在else语句中执行insert查询。有办法吗?

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

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

我想提一些事情

  1. 您的主要问题是您没有关闭DataReader。您可以使用using语句
  2. 您不需要明确打开和关闭SqlConnectionSqlCommand对象将根据需要执行此操作。
  3. 您不需要查看if (dr.HasRows),然后再次查看while (dr.Read())。此外,您不需要循环只选择一行数据。
  4. 理想情况下,我会把" Fetch"部分在一个单独的功能和"插入"在一个单独的功能中,功能保持小巧且可重复使用。
  5. 你的模式是多余的if (flag) {TakeAction();}否则if(!flag){TakeAction2();} . Every time the code hits the else , it will also hit the if(!flag)`
  6. sVendorDetails.VendorID = insertcmd.ExecuteNonQuery();看起来很腥。如果您的存储过程返回VendorId,那么您应该使用ExecuteScalar。目前它只是在所有情况下存储1,因为你可能会插入一行。
  7. 创建自定义SqlException时,不要丢弃原始ApplicationException。上游系统可能想知道比你传递的更多细节。将其作为InnerException
  8. 传递
  9. 我也改变了一些风格方面:
    1. 变量名称更改为更常用的camelCase,而不是错误使用的Hungarian NotationsVendorDetails而不是oVendorDetails
    2. 支持K& R风格
    3. 当右侧是var语句
    4. 时使用new
    5. 使用对象初始值设定项而不是创建+赋值
  10. 以下是代码

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