对象引用未设置为对象的实例 >> 插入查询 c#
object reference not set to an instance of an object >> insert query c#
我有这个方法将数据从文本框和 Datagridview
插入数据库中的两个不同表,第一个插入查询正常执行,但第二个插入查询抛出错误
Object reference not set to an instance of an object
这是我的方法:
private void InsertAll()
{
DialogResult Result = MessageBox.Show("Do you want to save all ? ", "Warnning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
if (Result == DialogResult.OK)
{
using (SqlCommand cmd = new SqlCommand())
{
try
{
cmd.Connection = Cn;
cmd.CommandType = CommandType.Text;
Cn.Open();
// Insert the header first Due to one-to-many relationship
cmd.CommandText = @" INSERT INTO DocDtls ( DocNum, zDate, Warehouse, Orientation,TransType,UserName )
VALUES (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6);";
cmd.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd.Parameters.AddWithValue("@prm2", txtDate.Value.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("@prm3", cmbWh.Text);
cmd.Parameters.AddWithValue("@prm4", txtOrient.Text);
cmd.Parameters.AddWithValue("@prm5", txtTransType.Text);
cmd.Parameters.AddWithValue("@prm6", txtUser.Text);
cmd.ExecuteNonQuery();
// Insert the Details >> where the problem start to occur
if (txtTransType.Text == "Release")
{
cmd2.Connection = Cn;
cmd2.CommandType = CommandType.Text;
// Cn.Open();
for (int i = 0; i < DGV1.Rows.Count; i++)
{
cmd2.CommandText = @"INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit)
VALUES (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6,@prm7);";
cmd2.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd2.Parameters.AddWithValue("@prm2", DGV1.Rows[i].Cells["Code"].Value);
cmd2.Parameters.AddWithValue("@prm3", 0);
cmd2.Parameters.AddWithValue("@prm4", DGV1.Rows[i].Cells["Qty"].Value);
cmd2.Parameters.AddWithValue("@prm5", DGV1.Rows[i].Cells["BalanceAfter"].Value);
cmd2.Parameters.AddWithValue("@prm6", DGV1.Rows[i].Cells["Remarks"].Value);
cmd2.Parameters.AddWithValue("@prm7", DGV1.Rows[i].Cells["Unit"].Value);
cmd2.ExecuteNonQuery();
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
{
cmd2.Connection = Cn;
cmd2.CommandType = CommandType.Text;
//Cn.Open();
for (int i = 0; i < DGV1.Rows.Count; i++)
{
cmd2.CommandText = @"INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit )
VALUES (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6,@prm7);";
cmd2.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd2.Parameters.AddWithValue("@prm2", DGV1.Rows[i].Cells["Code"].Value);
cmd2.Parameters.AddWithValue("@prm3", DGV1.Rows[i].Cells["Qty"].Value);
cmd2.Parameters.AddWithValue("@prm4", 0);
cmd2.Parameters.AddWithValue("@prm5", DGV1.Rows[i].Cells["BalanceAfter"].Value);
cmd2.Parameters.AddWithValue("@prm6", DGV1.Rows[i].Cells["Remarks"].Value);
cmd2.Parameters.AddWithValue("@prm7", DGV1.Rows[i].Cells["Unit"].Value);
cmd2.ExecuteNonQuery();
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString(), "Error Message",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
Cn.Close();
}
}
}
我怀疑连接可能在某个时候关闭,所以我在第一次插入后再次添加打开连接,但问题仍然存在。
我的代码有什么问题?
提前致谢
试试这个。有很多代码,所以可能还有一个错字或其他一两个问题。关注评论:
private void InsertAll()
{
using (var cn = new SqlConnection(Cn.ConnectionString)) // Using block around the connection
using (var cmd = new SqlCommand("", cn))
{
//removed the try/catch. Instead, wrap the try/catch around this method call
cmd.CommandText = @" INSERT INTO DocDtls ( DocNum, zDate, Warehouse, Orientation,TransType,UserName )
Values (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6);";
//AddWithValue() can be dangerously slow, but usually still safe for single simple INSERT
cmd.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd.Parameters.AddWithValue("@prm2", txtDate.Value); //If you're converting a DateTime to a string for use in SQL, you're doing something VERY WRONG
cmd.Parameters.AddWithValue("@prm3", cmbWh.Text);
cmd.Parameters.AddWithValue("@prm4", txtOrient.Text);
cmd.Parameters.AddWithValue("@prm5", txtTransType.Text);
cmd.Parameters.AddWithValue("@prm6", txtUser.Text);
cn.Open(); //Wait until last possible moment to call cn.Open()
cmd.ExecuteNonQuery();
// Normally don't re-use the same connection, but
// within a single operation context like this it's okay
// not only for the connection, but for the command, too.
cmd.CommandText = @" INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit )
Values (@DocNum, @Code, @QtyIn, @QtyOut, @BalanceAfter, @Remarks,@Unit);";
cmd.Parameters.Clear(); //Missing this line is why you had to create cmd2 before.
// Use exact types from the database here. Don't let ADO.Net try to infer these.
cmd.Parameters.Add("@DocNum", SqlDbType.VarChar, 10).Value = txtDocNum.Text;
cmd.Parameters.Add("@Code", SqlDbType.Char, 7);
// the "= 0" at the end of the next two lines are important.
cmd.Parameters.Add("@QtyIn", SqlDbType.Int).Value = 0;
cmd.Parameters.Add("@QtyOut", SqlDbType.Int).Value = 0;
cmd.Parameters.Add("@BalanceAfter", SqlDbType.Decimal);
cmd.Parameters.Add("@Remarks", SqlDbType.NVarChar, 1000);
cmd.Parameters.Add("@Unit", SqlDbType.NVarChar, 10);
// We can also set the Qty switch outside the loop
var qtyKey = (txtTransType.Text == "Release")?"@QtyOut":"@QtyIn";
for (int i = 0; i < DGV1.Rows.Count; i++)
{
// Only change parameter values inside the loop
cmd.Parameters["@Code"] = DGV1.Rows[i].Cells["Code"].Value;
cmd.Parameters[qtyKey].Value = DGV1.Rows[i].Cells["Qty"].Value;
cmd.Parameters["@BalanceAfter"] = DGV1.Rows[i].Cells["BalanceAfter"].Value;
cmd.Parameters["@Remarks"] = DGV1.Rows[i].Cells["Remarks"].Value;
cmd.Parameters["@Unit"] = DGV1.Rows[i].Cells["Unit"].Value;
cmd.ExecuteNonQuery();
}
// No need to call cn.Close(). Using blocks take care of it.
}
}
请注意,我删除了最初的 prompt/check、try/catch 和最后的完整消息。这些东西属于调用者,像这样:
DialogResult Result = MessageBox.Show("Do you want to save all ? ", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
if (Result == DialogResult.OK)
{
try
{
InsertAll()
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch(Exception e)
{
MessageBox.Show(e.Message.ToString(), "Error Message",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
最终,您还将将该方法(和其他数据库访问)移动为 单独 class 的静态成员,其中所需信息作为参数传递。
我有这个方法将数据从文本框和 Datagridview
插入数据库中的两个不同表,第一个插入查询正常执行,但第二个插入查询抛出错误
Object reference not set to an instance of an object
这是我的方法:
private void InsertAll()
{
DialogResult Result = MessageBox.Show("Do you want to save all ? ", "Warnning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
if (Result == DialogResult.OK)
{
using (SqlCommand cmd = new SqlCommand())
{
try
{
cmd.Connection = Cn;
cmd.CommandType = CommandType.Text;
Cn.Open();
// Insert the header first Due to one-to-many relationship
cmd.CommandText = @" INSERT INTO DocDtls ( DocNum, zDate, Warehouse, Orientation,TransType,UserName )
VALUES (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6);";
cmd.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd.Parameters.AddWithValue("@prm2", txtDate.Value.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("@prm3", cmbWh.Text);
cmd.Parameters.AddWithValue("@prm4", txtOrient.Text);
cmd.Parameters.AddWithValue("@prm5", txtTransType.Text);
cmd.Parameters.AddWithValue("@prm6", txtUser.Text);
cmd.ExecuteNonQuery();
// Insert the Details >> where the problem start to occur
if (txtTransType.Text == "Release")
{
cmd2.Connection = Cn;
cmd2.CommandType = CommandType.Text;
// Cn.Open();
for (int i = 0; i < DGV1.Rows.Count; i++)
{
cmd2.CommandText = @"INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit)
VALUES (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6,@prm7);";
cmd2.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd2.Parameters.AddWithValue("@prm2", DGV1.Rows[i].Cells["Code"].Value);
cmd2.Parameters.AddWithValue("@prm3", 0);
cmd2.Parameters.AddWithValue("@prm4", DGV1.Rows[i].Cells["Qty"].Value);
cmd2.Parameters.AddWithValue("@prm5", DGV1.Rows[i].Cells["BalanceAfter"].Value);
cmd2.Parameters.AddWithValue("@prm6", DGV1.Rows[i].Cells["Remarks"].Value);
cmd2.Parameters.AddWithValue("@prm7", DGV1.Rows[i].Cells["Unit"].Value);
cmd2.ExecuteNonQuery();
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
{
cmd2.Connection = Cn;
cmd2.CommandType = CommandType.Text;
//Cn.Open();
for (int i = 0; i < DGV1.Rows.Count; i++)
{
cmd2.CommandText = @"INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit )
VALUES (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6,@prm7);";
cmd2.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd2.Parameters.AddWithValue("@prm2", DGV1.Rows[i].Cells["Code"].Value);
cmd2.Parameters.AddWithValue("@prm3", DGV1.Rows[i].Cells["Qty"].Value);
cmd2.Parameters.AddWithValue("@prm4", 0);
cmd2.Parameters.AddWithValue("@prm5", DGV1.Rows[i].Cells["BalanceAfter"].Value);
cmd2.Parameters.AddWithValue("@prm6", DGV1.Rows[i].Cells["Remarks"].Value);
cmd2.Parameters.AddWithValue("@prm7", DGV1.Rows[i].Cells["Unit"].Value);
cmd2.ExecuteNonQuery();
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString(), "Error Message",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
Cn.Close();
}
}
}
我怀疑连接可能在某个时候关闭,所以我在第一次插入后再次添加打开连接,但问题仍然存在。
我的代码有什么问题?
提前致谢
试试这个。有很多代码,所以可能还有一个错字或其他一两个问题。关注评论:
private void InsertAll()
{
using (var cn = new SqlConnection(Cn.ConnectionString)) // Using block around the connection
using (var cmd = new SqlCommand("", cn))
{
//removed the try/catch. Instead, wrap the try/catch around this method call
cmd.CommandText = @" INSERT INTO DocDtls ( DocNum, zDate, Warehouse, Orientation,TransType,UserName )
Values (@prm1, @prm2, @prm3, @prm4, @prm5, @prm6);";
//AddWithValue() can be dangerously slow, but usually still safe for single simple INSERT
cmd.Parameters.AddWithValue("@prm1", txtDocNum.Text);
cmd.Parameters.AddWithValue("@prm2", txtDate.Value); //If you're converting a DateTime to a string for use in SQL, you're doing something VERY WRONG
cmd.Parameters.AddWithValue("@prm3", cmbWh.Text);
cmd.Parameters.AddWithValue("@prm4", txtOrient.Text);
cmd.Parameters.AddWithValue("@prm5", txtTransType.Text);
cmd.Parameters.AddWithValue("@prm6", txtUser.Text);
cn.Open(); //Wait until last possible moment to call cn.Open()
cmd.ExecuteNonQuery();
// Normally don't re-use the same connection, but
// within a single operation context like this it's okay
// not only for the connection, but for the command, too.
cmd.CommandText = @" INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit )
Values (@DocNum, @Code, @QtyIn, @QtyOut, @BalanceAfter, @Remarks,@Unit);";
cmd.Parameters.Clear(); //Missing this line is why you had to create cmd2 before.
// Use exact types from the database here. Don't let ADO.Net try to infer these.
cmd.Parameters.Add("@DocNum", SqlDbType.VarChar, 10).Value = txtDocNum.Text;
cmd.Parameters.Add("@Code", SqlDbType.Char, 7);
// the "= 0" at the end of the next two lines are important.
cmd.Parameters.Add("@QtyIn", SqlDbType.Int).Value = 0;
cmd.Parameters.Add("@QtyOut", SqlDbType.Int).Value = 0;
cmd.Parameters.Add("@BalanceAfter", SqlDbType.Decimal);
cmd.Parameters.Add("@Remarks", SqlDbType.NVarChar, 1000);
cmd.Parameters.Add("@Unit", SqlDbType.NVarChar, 10);
// We can also set the Qty switch outside the loop
var qtyKey = (txtTransType.Text == "Release")?"@QtyOut":"@QtyIn";
for (int i = 0; i < DGV1.Rows.Count; i++)
{
// Only change parameter values inside the loop
cmd.Parameters["@Code"] = DGV1.Rows[i].Cells["Code"].Value;
cmd.Parameters[qtyKey].Value = DGV1.Rows[i].Cells["Qty"].Value;
cmd.Parameters["@BalanceAfter"] = DGV1.Rows[i].Cells["BalanceAfter"].Value;
cmd.Parameters["@Remarks"] = DGV1.Rows[i].Cells["Remarks"].Value;
cmd.Parameters["@Unit"] = DGV1.Rows[i].Cells["Unit"].Value;
cmd.ExecuteNonQuery();
}
// No need to call cn.Close(). Using blocks take care of it.
}
}
请注意,我删除了最初的 prompt/check、try/catch 和最后的完整消息。这些东西属于调用者,像这样:
DialogResult Result = MessageBox.Show("Do you want to save all ? ", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
if (Result == DialogResult.OK)
{
try
{
InsertAll()
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch(Exception e)
{
MessageBox.Show(e.Message.ToString(), "Error Message",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
最终,您还将将该方法(和其他数据库访问)移动为 单独 class 的静态成员,其中所需信息作为参数传递。