【问题标题】:Is Delete Cascade enabled for a DbSet?是否为 DbSet 启用了删除级联?
【发布时间】:2013-11-15 10:14:25
【问题描述】:

使用实体框架,在从表中删除任何记录之前,如何判断是否为表启用了删除级联?

public partial class DataContext : DbContext
{
    public DbSet<Building> Buildings { get; set; }
    public DbSet<Room>     Rooms     { get; set; }
}

DataContext context;
Building    building;

// Will this start a DELETE CASCADE, removing Rooms within the Building?
context.Buildings.Remove(building);

这是一个通用函数,所以我可以使用 DbSet 或 DbContext 但不能使用 T。
需要在运行时进行测试,就在调用 Remove() 之前。

您能否在删除之前检测到 DELETE CASCADE,如果可以,如何检测?

【问题讨论】:

  • 应该只通过实体框架吗?因为通过 T-SQL 是小菜一碟。
  • 我个人认为您不应该为任何表设置级联删除。在我看来,这在任何时候都是一个非常糟糕的主意,因为您最终可能会删除一条记录并锁定许多表并删除数百万条相关记录,这会使您的系统戛然而止。此外,子记录的存在通常是为什么不应该删除父记录的关键。例如,您不应该删除过去有订单的客户。您可能会考虑使用软增量方案。
  • 好吧,假设必须删除记录,我更希望自动发生(而不是手动,这会涉及人为错误)。

标签: c# sql entity-framework generics


【解决方案1】:

您可以很容易地使用 t-sql 函数或查询来为您提供所需的信息。尝试使用您想要的任何谓词包装以下内容(例如 WHERE PK.TABLE_NAME = 'My Table' AND C.DELETE_RULE = 'CASCADE'。如果记录 a 存在,那么您已经获得了所需的信息。

SELECT
    FK_TableName = FK.TABLE_SCHEMA + '.' + FK.TABLE_NAME,
    FK_ColumnName = CU.COLUMN_NAME,
    PK_TableName = PK.TABLE_SCHEMA + '.' + PK.TABLE_NAME,
    PK_ColumnName = PT.COLUMN_NAME,
    ConstraintName = C.CONSTRAINT_NAME,
    DeleteRule = C.DELETE_RULE
FROM
    INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
    ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
    ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
    ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN (
    SELECT
        i1.TABLE_NAME,
        i2.COLUMN_NAME
    FROM
        INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
        ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
    WHERE
        i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
   ) PT ON PT.TABLE_NAME = PK.TABLE_NAME;

然后您可以将其包装到 DbSet 扩展中,并像 context.Set&lt;MyEntity&gt;().UsesCascadeDelete() 一样调用它,它会使用您的谓词和您想要的任何其他内容触发上述查询。

因为 EF 可以非常轻松地运行 TSQL 查询,所以我仍然认为它们是 EF 的“一部分”。

【讨论】:

  • 作为旁注,我没有写上面的查询,而是很久以前从某人那里提取的。如果我找到那个人,我会相信他们。此外,该查询在集成测试中对我们来说非常棒……我们检查所有主键、外键约束,以确保数据库完全符合我们的预期。
  • 毫无疑问我可以使用这样的查询,但问题是 - 如何?
【解决方案2】:

Read FK Metadata”或“Check an entity for FK usage”会有帮助吗?似乎有几种方法可以尝试,尽管我也没有尝试过。

我通常会手动检查mappings files 和代码存储库,并牢记这些知识。也许之前的 Stackoverflow 答案将使您能够根据需要创建更通用的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    相关资源
    最近更新 更多