【问题标题】:Deleting an entity from a table which is dependent on another table从依赖于另一个表的表中删除实体
【发布时间】:2009-09-27 20:23:55
【问题描述】:

我有 2 个表 MachineGroups 和 Machines。 MachineGroups 有列:

  • 机器组ID
  • 机器组名
  • MachineGroupDesc

而且机器有栏目:

  • 机器组 ID (FK)
  • 机器ID
  • 机器名称
  • 机器

现在我想删除一个机器组,但不是其中有机器的那些。 所以如果有机器它应该给出一个错误信息....说你不能删除。

这就是我想要做的......

<asp:GridView ID="GridView1" runat="server" AllowSorting="True"
    AutoGenerateColumns="False" CellPadding="1" CellSpacing="2"
    DataSourceID="SqlDataSource1" ForeColor="#333333" GridLines="None"
     Width="100%" ondatabound="GridView1_DataBound1"
    onrowdatabound="GridView1_RowDataBound1">
    <RowStyle BackColor="#D0D8E8" ForeColor="#333333" Height="35px" />
    <Columns>
        <asp:BoundField DataField="MachineGroupID" HeaderText="MachineGroupID" 
            InsertVisible="False" ReadOnly="True" SortExpression="MachineGroupID" 
            Visible="False" />
        <asp:BoundField DataField="MachineGroupName" HeaderText="MachineGroupName" 
            SortExpression="MachineGroupName" />
        <asp:BoundField DataField="MachineGroupDesc" HeaderText="MachineGroupDesc" 
            SortExpression="MachineGroupDesc" />
        <asp:BoundField DataField="TimeAdded" HeaderText="TimeAdded" 
            SortExpression="TimeAdded" />
        <asp:TemplateField HeaderText="CanBeDeleted" SortExpression="CanBeDeleted" 
            Visible="False">
            <EditItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server"
                    Checked='<%# Bind("CanBeDeleted") %>' />
            </EditItemTemplate>
            <ItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server"
                    Checked='<%# Bind("CanBeDeleted") %>' Enabled="false" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="No. of PCs" HeaderText="No. of PCs" ReadOnly="True"
            SortExpression="No. of PCs" />
        <asp:TemplateField ShowHeader="False">
            <ItemTemplate>
                <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False"
                    CommandName="Delete" Text="Delete"></asp:LinkButton>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
    <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
    <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
    <HeaderStyle BackColor="#4F81BD" Font-Bold="True" ForeColor="White"
        Height="30px" />
    <EditRowStyle BackColor="#999999" />
    <AlternatingRowStyle BackColor="#E9EDF4" ForeColor="#284775" />
</asp:GridView>


<asp:SqlDataSource ID="SqlDataSource1" runat="server"         ConnectionString="<%$ ConnectionStrings:SumooHAgentDBConnectionString %>" 
    SelectCommand="SELECT MachineGroups.MachineGroupID, MachineGroups.MachineGroupName, MachineGroups.MachineGroupDesc, MachineGroups.TimeAdded, MachineGroups.CanBeDeleted, COUNT(Machines.MachineName) AS 'No. of PCs' FROM MachineGroups FULL OUTER JOIN Machines ON Machines.MachineGroupID = MachineGroups.MachineGroupID GROUP BY MachineGroups.MachineGroupID, MachineGroups.MachineGroupName, MachineGroups.MachineGroupDesc, MachineGroups.TimeAdded, MachineGroups.CanBeDeleted" 
    DeleteCommand="DELETE FROM MachineGroups WHERE (MachineGroupID = @original_MachineGroupID) AND (MachineGroupName = @original_MachineGroupName) AND (MachineGroupDesc = @original_MachineGroupDesc) AND (CanBeDeleted = @original_CanBeDeleted) AND (TimeAdded = @original_TimeAdded)">
    <DeleteParameters>
        <asp:Parameter Name="original_MachineGroupID" />
        <asp:Parameter Name="original_MachineGroupName" />
        <asp:Parameter Name="original_MachineGroupDesc" />
        <asp:Parameter Name="original_CanBeDeleted" />
        <asp:Parameter Name="original_TimeAdded" />
    </DeleteParameters>
</asp:SqlDataSource>

请提出建议..

【问题讨论】:

  • 这对于 SQL 或带有 C# 的 SQL 来说都不是一个难题。但是,要求我们也是 ASP.Net 方面的专家可能会大大缩小您的潜在帮助者的范围。如果您可以分阶段解决这个问题,以便我们不必从 XML/HTML(或其他任何内容)中挑出 SQL,应用 SQL 解决方案,然后弄清楚如何再次将其重新应用到您的 ASP.net,您可能会得到更多/更好的答案。
  • 哎呀,这是“短语”而不是“阶段”。
  • @RBarryYoung,看到 OP 正在使用 SqlDataSource,不涉及多余代码的问题的解决方案是非常特定于 ASP.NET 的。

标签: c# asp.net sql-server sql-server-2005


【解决方案1】:

处理您的 GridView 的 RowDeletingRowDeleted 事件。在RowDeleting中,可以运行Palo建议的查询,并运行查询检查组是否为空:

protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    int mgid = e.Keys["MachineGroupId"];
    if (!GroupIsEmpty(mgid))
    {
        e.Cancel = true;
    }
}

在“RowDeleted”中,您可以检查是否存在异常,因为当您的约束正常工作时应该有,并且您不会如上所述取消删除:

protected void GridView1_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
    if ((e.Exception != null) && (e.ExceptionHandled))
    {
        errorLabel.Text = "Machine group could not be deleted.  This is probably because machines still exist for the group.";
    }
}

【讨论】:

    【解决方案2】:

    在良好的旧 SQL 中,您需要做的就是删除 MachineGroups 中未在 Machines 表中列为 MachineGroupID 的条目:

    DELETE FROM MachineGroups
     WHERE MachineGroupID NOT IN (SELECT DISTINCT MachineGroupID FROM Machines)
    

    如何将其转换为 ASP/XML 是任何人的猜测。

    【讨论】:

    • 我认为他不想删除所有没有任何机器的机器组。他想要处理特定机器组的删除按钮按下,如果该机器组中仍有任何机器,则抛出错误。
    • @Mark:所以他需要添加“AND MachineGroupID = 123456”。这将删除组 123456,除非它仍然有条目。他必须分析删除的行数才能知道该行是否被删除;删除零行并不是失败。
    【解决方案3】:

    我假设您在MachinesMachineGroups 这两个表之间有外键关系,对吧? (基于 MachineGroupID)

    如果那个 FK 关系没有指定ON DELETE CASCADE 选项,那么你可以做的是

    • 尝试删除机器组
    • 捕获任何可能发生的异常,表明由于现有子行而无法删除它
    • 向用户显示该消息(或更方便用户的“翻译”)

    如果 FK 关系确实指定了 ON DELETE CASCADE 选项,那么在删除该机器组之前,您必须首先检查以确保给定 MachineGroupID 没有子行。

    马克

    【讨论】:

    • 你刚才说的是对的......但我没有删除级联选项..所以我不得不使用第二个选项......你能帮我吗..
    【解决方案4】:

    对具有该组 ID 的机器进行简单计数:

    select count(id) from Machines where MachineGroupId == groupIdToDelete;
    

    如果有计数,您可以显示一个不错的错误消息或其他任何内容。

    如果没有计数,继续删除。

    【讨论】:

      【解决方案5】:

      您需要先删除子行。所以也许有2个删除程序。比如:

      DELETE 
      FROM machines 
      WHERE
      MachineGroupID = @IN_MachineGroupID
      
      DELETE 
      FROM machinesGroups 
      WHERE
      MachineGroupID = @IN_MachineGroupID
      

      在我看来,使用 DataSet 和 DataAdapter 可以使这更容易。查看 ADO.Net 断开层。

      我注意到你想抛出一个错误 - 你有代码隐藏页面吗?

      你需要做的

      Try
      {
         call your delete;
      }
      catch(Exception ex)
      {
         throw (ex.Messgae)
      }
      

      您可以更准确地了解您要查找的错误,但您明白了。

      【讨论】:

      • 我不需要删除子行...我只需要在标签中显示错误消息...那么有没有办法删除没有任何机器的行并显示错误对于那些有机器的人......
      猜你喜欢
      • 2014-12-04
      • 1970-01-01
      • 2021-06-07
      • 1970-01-01
      • 2011-01-02
      • 2011-06-12
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多