如果“DELETE 语句与 REFERENCE 约束冲突”,则取消“删除”事件

本文关键字:删除 事件 取消 约束 语句 DELETE REFERENCE 如果 冲突 | 更新日期: 2023-09-27 18:34:11

我使用的是System.Data.EntityClient而不是简单的System.Data.SqlClient

我是实体框架的新手,所以请原谅我的无知,请不要提供神秘的回应,因为我没有必要的背景信息来理解它们。

我做了几个小时的研究,但找不到解决我问题的正确答案组合。

问题:

当触发"删除"事件时,页面会引发此错误:

DELETE 语句与 REFERENCE 约束冲突

我想捕获该错误并让它在页面上填充一个标签,上面写着

无法删除此客户

我的ASP页面:

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<p>
    <asp:DetailsView ID="CustomerDetail" runat="server" 
        DataSourceID="CustomerSqlDataSource" Height="50px" 
        Width="215px" Visible="False" AutoGenerateRows="False" 
        OnModeChanged="CustomerDetail_ModeChanged">
        <Fields>
            <asp:BoundField DataField="FirstName" HeaderText="First Name:" />
            <asp:BoundField DataField="LastName" HeaderText="Last Name:" />
            <asp:BoundField DataField="City" HeaderText="City:" />
            <asp:BoundField DataField="State" HeaderText="State" />
            <asp:CommandField ShowInsertButton="True" />
        </Fields>
    </asp:DetailsView>
</p>
<asp:Button ID="NewCustomerButton" runat="server" Text="New Customer" OnClick="NewCustomerButton_Click" />
<p>
    <asp:Label ID="DeleteLabel" runat="server" Text="" Visible="false"/>
    <asp:GridView ID="CustomerGrid" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="CustomerId" DataSourceID="CustomerSqlDataSource" 
        OnSelectedIndexChanged="CustomerGrid_SelectedIndexChanged" >
        <Columns>
            <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
            <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
            <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
            <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
            <asp:BoundField DataField="State" HeaderText="State" SortExpression="State" />
        </Columns>
    </asp:GridView>
    <br />
    <br />
    <asp:SqlDataSource ID="CustomerSqlDataSource" runat="server" 
        ConnectionString="<%$ ConnectionStrings:ITP236-InventoryConnectionString %>" 
        DeleteCommand="DELETE FROM [Customer] WHERE [CustomerId] = @CustomerId" 
        InsertCommand="INSERT INTO [Customer] ([FirstName], [LastName], [City], [State]) 
                        VALUES (@FirstName, @LastName, @City, @State)" 
        SelectCommand="SELECT [CustomerId], [FirstName], [LastName], [City], [State] FROM [Customer]" 
        UpdateCommand="UPDATE [Customer] 
                        SET [FirstName] = @FirstName, [LastName] = @LastName, [City] = @City, [State] = @State 
                        WHERE [CustomerId] = @CustomerId" OnDeleted="CustomerSqlDataSource_Deleted">
        <DeleteParameters>
            <asp:Parameter Name="CustomerId" Type="Int32" />
        </DeleteParameters>
        <InsertParameters>
            <asp:Parameter Name="FirstName" Type="String" />
            <asp:Parameter Name="LastName" Type="String" />
            <asp:Parameter Name="City" Type="String" />
            <asp:Parameter Name="State" Type="String" />
        </InsertParameters>
        <UpdateParameters>
            <asp:Parameter Name="FirstName" Type="String" />
            <asp:Parameter Name="LastName" Type="String" />
            <asp:Parameter Name="City" Type="String" />
            <asp:Parameter Name="State" Type="String" />
            <asp:Parameter Name="CustomerId" Type="Int32" />
        </UpdateParameters>
    </asp:SqlDataSource>
</p>

其背后的代码不起作用:

protected void CustomerSqlDataSource_Deleted(object sender, SqlDataSourceStatusEventArgs e)
{
     if (e.ExceptionHandled == false)
     {
      e.Command.Cancel();
      DeleteLabel.Visible = true;
      DeleteLabel.Text = "This Customer cannot be deleted";
     }
}
=========================================================================================================================================================================================================================================

===

在美国东部标准时间上午 11:41 编辑以包含整个错误。 虽然,我明白问题是什么,我只是想在此错误显示之前捕获此错误并将其带回页面上的标签,并让标签显示"无法删除客户">

=========================================================================================================================================================================================================================================

==="/"应用程序中的服务器错误。

DELETE 语句与 REFERENCE 约束"FK_SalesOrder_Customer"冲突。冲突发生在数据库"ITP236-清单"中,表"dbo.销售订单",列"客户 ID"。该语句已终止。

说明:执行当前 Web 请求期间发生未经处理的异常。请查看堆栈跟踪,了解有关错误及其在代码中起源位置的详细信息。

异常详细信息:System.Data.SqlClient.SqlException:DELETE 语句与 REFERENCE 约束"FK_SalesOrder_Customer"冲突。冲突发生在数据库"ITP236-清单"中,表"dbo.销售订单",列"客户 ID"。该语句已终止。

源错误:

执行当前 Web 请求期间生成了未经处理的异常。可以使用下面的异常堆栈跟踪来识别有关异常来源和位置的信息。

堆栈跟踪:

[SqlException (0x80131904(:DELETE 语句与 REFERENCE 约束"FK_SalesOrder_Customer"冲突。冲突发生在数据库"ITP236-清单"中,表"dbo.销售订单",列"客户 ID"。该声明已终止。 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction) +1767866 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction( +5352418 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose( +244 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady( +1691 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString( +269 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds( +1406 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource 1 completion, Int32 timeout, Task& task, Boolean asyncWrite) +177 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource 1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite( +205 System.Data.SqlClient.SqlCommand.ExecuteNonQuery(( +160 System.Web.UI.WebControls.SqlDataSourceView.ExecuteDbCommand(DbCommand command, DataSourceOperation operation( +380 System.Web.UI.WebControls.SqlDataSourceView.ExecuteDelete(IDictionary keys, IDictionary oldValues( +568 System.Web.UI.DataSourceView.Delete(IDictionary keys, IDictionary oldValues, DataSourceViewOperationCallback callback( +84 System.Web.UI.WebControls.GridView.HandleDelete(GridViewRow row, Int32 rowIndex( +930 System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup( +974 System.Web.UI.WebControls.GridView.RaisePostBackEvent(String eventArgument( +205 System.Web.UI.WebControls.GridView.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument( +13 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument( +13 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData( +9671830 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint( +1724

版本信息: Microsoft .NET 框架版本:4.0.30319

;ASP.NET 版本:4.0.30319.34237

如果“DELETE 语句与 REFERENCE 约束冲突”,则取消“删除”事件

您收到的错误是由于违反了外键约束。Customer表的主键在某个其他表的外键约束中引用。您无法删除客户,因为其他一些表取决于客户。

例如,如果有一个Orders表,其中有一个CustomerId列引用您尝试删除的客户,该怎么办?客户订购产品,因此没有客户就无法存在订单。在这种情况下,请尝试更改 DELETE 语句:

DELETE FROM [Customer] WHERE [CustomerId] = @CustomerId
AND NOT EXISTS (SELECT * FROM [Orders] AS o WHERE o.[CustomerId]=@CustomerId)

这将防止删除有订单的客户。您可以在 Deleted 事件中按如下方式处理此问题:

protected void CustomerSqlDataSource_Deleted(object sender, SqlDataSourceStatusEventArgs e)
{
    if (e.AffectedRows == 0)
    {
        DeleteLabel.Visible = true;
        DeleteLabel.Text = "This Customer cannot be deleted because it has orders";
    }
}

您可以通过选中e.Exception != null而不是e.ExceptionHandled == false来处理异常。

protected void CustomerSqlDataSource_Deleted(object sender, SqlDataSourceStatusEventArgs e)
{
     try {
         if (e.ExceptionHandled == false)
         {
         e.Command.Cancel();
         DeleteLabel.Visible = true;
         DeleteLabel.Text = "This Customer cannot be deleted";
     }
     catch {
       // do your thing here when error occurs
     }
}