4

好吧,这是我的情况:

我们有我们不想删除数据的表。有一个名为 isDeleted 的列应该更新而不是删除它。

我想用 EF5 开发随附的 Web 应用程序,但我有一个问题。我如何实施该限制?

我可以使用存储过程来删除和选择,但我希望有一种方法可以在 EF 中使用标准函数,只是改变它们的工作方式。哪种方式不那么艰巨,我必须有哪些选择来实现我想要的,因为我猜我不是第一个要求这个的人?

4

3 回答 3

4

您可以覆盖 DbContext 的 SaveChanges 方法。例如,您想禁止删除产品。您可以保存 IsDeleted 标志设置为 true 的实体,而不是删除它们:

public override int SaveChanges()
{
    var deletedPersonEntries = ChangeTracker.Entries<Person>()
                                    .Where(e => e.State == EntityState.Deleted);

    foreach (var e in deletedPersonEntries)
    {
        e.State = EntityState.Unchanged;
        e.Entity.IsDeleted = true;
    }

    return base.SaveChanges();
}

另一种选择 - 如果有人试图删除产品,则引发异常:

if (deltedProductEntries.Any())
    throw new Exception("You should not delete products!");

您也可以简单地将实体状态设置为不变,但我认为这不是很好的解决方案。

于 2013-09-24T16:13:52.027 回答
1

你可以这样做:

  1. 在 OnModelCreating 中为每个可以软删除的实体添加一个 IsDeleted 鉴别器
  2. 覆盖 SaveChanges 并找到所有要删除的条目
  3. 对这些条目运行 SQL 以设置 IsDeleted 鉴别器,然后将它们的状态设置为“分离”
  4. 更改任何唯一索引以忽略任何软删除记录

您可以在此答案中找到工作代码: How to soft delete using Entity Framework Code First

您也可以使用存储过程而不是步骤 2 和 3 中使用的代码 - 我一直在研究EF6 如何为您生成存储过程。您添加如下所示的代码:

modelBuilder.Entity<AdministrativeArea>().MapToStoredProcedures();

这会导致迁移包括以下内容:

        CreateStoredProcedure(
            "dbo.AdministrativeArea_Delete",
            p => new
                {
                    ID = p.Int(),
                },
            body:
                @"DELETE [dbo].[AdministrativeAreas]
                  WHERE ([ID] = @ID)"
        );

现在是一个将迁移中的sql从删除更改为更新的情况。用 text/replace 来做这件事不会太费力,但如果我们可以更改用于生成CreateStoredProcedure调用的模板,那不是很酷吗?......

于 2013-09-26T08:11:30.023 回答
0
CREATE VIEW Foo
AS 
SELECT
    f.Id,
    f.Bar,
    f.Baz,
    f.Qux
FROM Foo_Table
Where f.Deleted = 0;

CREATE TRIGGER Foo_Delete
ON Foo
Instead of Delete
AS 
BEGIN
    Update
        Foo_Table f
    SET
        f.Deleted = 1
    WHERE
        f.Id IN (SELECT Id from Deleted)
END;
于 2013-09-24T15:50:45.287 回答