【问题标题】:EF5: How to alter the default Delete function to implement my ownEF5:如何更改默认删除功能以实现我自己的
【发布时间】:2013-09-24 15:05:46
【问题描述】:

嗯,这是我的情况:

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

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

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

【问题讨论】:

  • 我不寒而栗地提出这个建议,但你考虑过触发器吗?你可以做一个instead of delete
  • 是的,但是下一个选择仍然会获取数据..我想要的是所有选择调用来忽略那些“已删除”的行
  • @Sergio 你现在在谈论两件不同的事情,软删除数据和过滤掉 deleted 的记录。
  • 我正在添加我不喜欢的建议,但您可以在表格周围包裹一个仅返回“未删除”记录的视图,并将其设为您的实体。此时您需要在视图上触发。
  • 我在这里发布了一个相当完整的解决方案。 stackoverflow.com/a/18985828/150342

标签: .net entity-framework


【解决方案1】:

您可以覆盖 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!");

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

【讨论】:

  • 对于您的第三个选项,我会选择 e.State = EntityState.Unchanged; e.Entity.IsDeleted = true;,这样只会更新 IsDeleted,而不是其他所有内容。
【解决方案2】:

你可以这样做:

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

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

您也可以使用存储过程来代替步骤 2 和 3 中使用的代码 - 我一直在研究 EF6 generates the stored procedures for you 的方法。您添加如下代码:

modelBuilder.Entity&lt;AdministrativeArea&gt;().MapToStoredProcedures();

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

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

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

【讨论】:

    【解决方案3】:
    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多