好吧,这是我的情况:
我们有我们不想删除数据的表。有一个名为 isDeleted 的列应该更新而不是删除它。
我想用 EF5 开发随附的 Web 应用程序,但我有一个问题。我如何实施该限制?
我可以使用存储过程来删除和选择,但我希望有一种方法可以在 EF 中使用标准函数,只是改变它们的工作方式。哪种方式不那么艰巨,我必须有哪些选择来实现我想要的,因为我猜我不是第一个要求这个的人?
好吧,这是我的情况:
我们有我们不想删除数据的表。有一个名为 isDeleted 的列应该更新而不是删除它。
我想用 EF5 开发随附的 Web 应用程序,但我有一个问题。我如何实施该限制?
我可以使用存储过程来删除和选择,但我希望有一种方法可以在 EF 中使用标准函数,只是改变它们的工作方式。哪种方式不那么艰巨,我必须有哪些选择来实现我想要的,因为我猜我不是第一个要求这个的人?
您可以覆盖 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!");
您也可以简单地将实体状态设置为不变,但我认为这不是很好的解决方案。
你可以这样做:
您可以在此答案中找到工作代码: 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
调用的模板,那不是很酷吗?......
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;