我有一个表名AVUKAT及其列(AVUKAT
,HESAP
(主键),MUSTERI
)
所有MUSTERI
都有一个唯一的HESAP
(int)。
简单我有这样的页面。
第一个下拉选择MUSTERI,第二个是AVUKAT
我用这段代码自动计算HESAP(int
和Primary KEY
)。 (在背景上。)
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
string strConnectionString = ConfigurationManager.ConnectionStrings["SqlServerCstr"].ConnectionString;
SqlConnection myConnection = new SqlConnection(strConnectionString);
myConnection.Open();
string hesapNo = DropDownList1.SelectedItem.Value;
string query = "select A.HESAP_NO from YAZ..MARDATA.S_TEKLIF A where A.MUS_K_ISIM = '" + hesapNo + "'";
SqlCommand cmd = new SqlCommand(query, myConnection);
if (DropDownList1.SelectedValue != "0" && DropDownList2.SelectedValue != "0")
{
Add.Enabled = true;
Label1.Text = cmd.ExecuteScalar().ToString();
}
else
{
Add.Enabled = false;
}
Label1.Visible = false;
myConnection.Close();
}
我只是用这段代码计算HESAP
。
我的ADD
按钮点击功能是;
protected void Add_Click(object sender, EventArgs e)
{
try
{
string strConnectionString = ConfigurationManager.ConnectionStrings["SqlServerCstr"].ConnectionString;
SqlConnection myConnection = new SqlConnection(strConnectionString);
myConnection.Open();
string hesap = Label1.Text;
string musteriadi = DropDownList1.SelectedItem.Value;
string avukat = DropDownList2.SelectedItem.Value;
SqlCommand cmd = new SqlCommand("INSERT INTO AVUKAT VALUES (@MUSTERI, @AVUKAT, @HESAP)", myConnection);
cmd.Parameters.AddWithValue("@HESAP", hesap);
cmd.Parameters.AddWithValue("@MUSTERI", musteriadi);
cmd.Parameters.AddWithValue("@AVUKAT", avukat);
cmd.Connection = myConnection;
SqlDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
Response.Redirect(Request.Url.ToString());
myConnection.Close();
}
catch (Exception)
{
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), " ", "alert('Bu Müşteri Zaten Mevcut!')", true);
}
}
使用try catch
的原因,如果有人尝试为MUSTERI添加具有相同HESAP(int)值的add,则显示错误消息并且不添加该表。
但是当我尝试添加相同的MUSTERI(也是相同的HESAP)时,添加HESAP = 0值的相同MUSTERI。
我该如何预防这种情况?我选择HESAP列是主键,但仍然添加相同的MUSTERI。
答案 0 :(得分:5)
这里没有什么可以解释你所看到的行为。最可能的问题是在执行插入之前Label1.Text
的值是0
,可能在ASP.NET页面生命周期的其他地方设置。确保在hesap
初始化Add_Click
之后添加一行代码,如...
Response.Write("<strong>hesap == " + hesap + "</strong>");
...并注释掉Response.Redirect
,以便您可以看到输出。
您还可以对代码进行一些改进,以减少问题发生的时间。
清理避免SQL注入的输入非常重要。希望您已在其他地方执行此操作,但未在您的代码段中显示。如果您不知道这是什么,那么这里有heaps of questions about it。
此外,您不是为了检索任何行而进行查询,因此使用ExecuteNonQuery
。所以我也要换掉这条线......
SqlDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
...与...
int numberOfRows = cmd.ExecuteNonQuery();
然后检查ExecuteNonQuery
的值以确保numberOfRows
== 1,以便您了解实际发生的事情。
您还应该使用 SqlConnection
语句包装SqlCommand
和using
初始化者。这意味着即使出现问题,它们也会自动处理。这样可以防止内存问题和连接处于打开状态的问题。
最后,通过将该行更改为catch
,让异常值通过进入catch (Exception ex)
语句。使用ex.ToString()
输出异常以查看其所有详细信息。现在你不知道如果发生异常会出现什么问题。
答案 1 :(得分:2)
HESAP是主键。但是,MUSTERI是否也有一个唯一约束,可以阻止某人输入两个MUSTERI值?这至少会阻止数据进入数据库。如下所示:
Alter Table AVUKAT Add Constraint UC_AVUKAT Unique ( MUSTERI )
HESAP上是否存在CHECK约束,要求该值大于零?如下所示:
Alter Table AVUKAT Add Constraint CK_AVUKAT_HESAP Check ( HESAP > 0 )
应该注意MySQL将忽略Check约束。因此,您需要在触发器中强制执行此规则。但是,许多数据库系统(如SQL Server,Oracle,Postgres,Informix等)都会强制执行检查约束。
我会进行以下修订
using
语句来确保处理我的对象。ExecuteNonQuery
并使用返回的行数来确定查询是否没有插入任何内容而不是实现全局catch-all。除非您确切知道您期望的错误,否则不应使用Catch ( Exception )
来捕获任何异常,无论类型如何。protected void Add_Click(object sender, EventArgs e)
{
string strConnectionString = ConfigurationManager.ConnectionStrings["SqlServerCstr"].ConnectionString;
using( SqlConnection myConnection = new SqlConnection(strConnectionString) )
{
myConnection.Open();
string hesap = Label1.Text;
string musteriadi = DropDownList1.SelectedItem.Value;
string avukat = DropDownList2.SelectedItem.Value;
string sql = @"INSERT INTO AVUKAT( MUSTERI, AVUKAT, HESAP)
Select @MUSTERI, @AVUKAT, @HESAP
From ( Select 1 As Value ) As Z
Where Not Exists (
Select 1
From AVUKAT As T1
Where T1.HESAP = @HESAP
)";
using ( SqlCommand cmd = new SqlCommand(sql, myConnection) )
{
cmd.Parameters.AddWithValue("@HESAP", hesap);
cmd.Parameters.AddWithValue("@MUSTERI", musteriadi);
cmd.Parameters.AddWithValue("@AVUKAT", avukat);
cmd.Connection = myConnection;
int rowsAffected = cmd.ExecuteNonQuery();
if ( rowsAffected = 0 )
// tell user that ID exists and their data couldn't be inserted.
Response.Redirect(Request.Url.ToString());
myConnection.Close();
}
}
}
当你消除不可能的事物时,无论多么不可能,遗体都必须是真理。
如果插入的HESAP值为零,则在触发Add_Click事件时Label1.Text必须包含零。查看DropDown事件处理程序,有几个值得注意的事项。
int.TryParse
验证它是一个整数。using
构造。protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
int avukat;
int hesapNo;
bool enabled = int.TryParse( DropDownList1.SelectedItem.Value, out hesapNo )
&& int.TryParse( DropDownList2.SelectedItem.Value, out avukat )
&& hesapNo != 0
&& avukat != 0;
if ( enabled )
{
string strConnectionString = ConfigurationManager.ConnectionStrings["SqlServerCstr"].ConnectionString;
using( SqlConnection myConnection = new SqlConnection(strConnectionString) )
{
myConnection.Open();
string query = @"Select A.HESAP_NO
From YAZ..MARDATA.S_TEKLIF A
Where A.MUS_K_ISIM = @HesapNo"
using( SqlCommand cmd = new SqlCommand(query, myConnection) )
{
cmd.AddParameterWithValue( "@HesapNo", hesapNo );
Label1.Text = cmd.ExecuteScalar().ToString();
}
}
}
Add.Enabled = enabled;
Label1.Visible = false;
}
如果你添加我在顶部提到的CHECK约束,那么代码将在插入时出错,坏行将不会进入数据库。这应该会引导您回到DropDownList1的DataSource。它的SelectedValue似乎返回为零。这意味着填充DropDownList1的源正在推送一个零值。填充DropDownList1的来源是什么?
答案 2 :(得分:1)
也许您应该尝试将示例数据直接插入数据库并尝试测试向表中添加相同的MUSTERI和HESAP。你应该得到一个错误。
我认为你应该修改你在Add_Click
SqlCommand cmd = new SqlCommand("INSERT INTO AVUKAT VALUES (@MUSTERI, @AVUKAT, @HESAP)", myConnection);
它应该是:
SqlCommand cmd = new SqlCommand("INSERT INTO AVUKAT (MUSTERI, AVUKAT, HESAP) VALUES (@MUSTERI, @AVUKAT, @HESAP)", myConnection);
希望这有帮助
答案 3 :(得分:1)
答案 4 :(得分:1)
如果不查看您的数据库架构,很难对此处发生的事情做出任何真实的猜测,但我可能会提出以下建议。
您的数据库是否为您不想复制的两个值设置了唯一索引?
您的数据库表是否已设置为自动生成主键,或者您是否手动管理主键?
是否有任何触发器导致问题?
您确定负责显示主键列的代码是否在所有情况下都正确检索?
插入物实际发生了吗?如果未发生插入,则您将看到积分值的默认值,该值为零。
答案 5 :(得分:1)
如果错误发生在添加按钮事件中,则恶意Response.Redirect(Request.Url.ToString());
交换connection.close()
和response.redirect
。因为页面重定向后myconnection对象丢失了。
那应该是这种方式
myconnection.close();
Response.redirect("url",false);
我认为它会起作用..
答案 6 :(得分:1)
我的下一步是启动分析器并找出您的应用程序实际发送到SQL Server的内容。确保输入的值符合您的预期,然后直接在SSMS / QA中执行查询,以确保其行为符合预期。
我和Alex在一起,因为罪魁祸首可能是你标签上的意外值。确定SQL Server正在查看什么,以便您知道在整个页面生命周期中哪个值需要更多关注。
答案 7 :(得分:1)
在尝试添加重复记录时,您是否在两个下拉菜单中选择了值?我可以猜测你没有选择AVUKAT的第二个下拉列表,因此你的Label1.Text
被设置为null,导致为主键插入0。