问题
Well, here is my situation:
We have tables that we dont want ever to delete the data. There is a column which is called isDeleted that is supposed to be updated instead instead of deleting it.
I want to develop the accompanying web app with EF5 but i have a problem there. How do i implement that restriction?
I could use stored procedures to delete and select but i was hoping for a way to use the standard functions in EF, just changing how they work. Which way is less arduous and what options i have to achieve what i want, since i´m guessing i´m not the first person to ask for this?
回答1:
You can override SaveChanges method of your DbContext. E.g. you want to forbid deleting products. You can save entities with IsDeleted flag set to true instead of deleting them:
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();
}
Another option - raise exception if someone tries to delete product:
if (deltedProductEntries.Any())
throw new Exception("You should not delete products!");
You also can simply set entities state to unchanged, but I don't think its very good solution.
回答2:
You can do it like this:
- In OnModelCreating add an IsDeleted discriminator to every entity that can be soft deleted
- Override SaveChanges and find all the entries to be deleted
- Run SQL on these entries to set the IsDeleted discriminator then set their state to "detached"
- Change any unique indexes to ignore any soft deleted records
You can find working code at this answer: How to soft delete using Entity Framework Code First
You could also use stored procedures instead of the code used in steps 2 and 3 - and I've been looking at how EF6 generates the stored procedures for you. You add code that looks like this:
modelBuilder.Entity<AdministrativeArea>().MapToStoredProcedures();
and that results in a migration that includes this:
CreateStoredProcedure(
"dbo.AdministrativeArea_Delete",
p => new
{
ID = p.Int(),
},
body:
@"DELETE [dbo].[AdministrativeAreas]
WHERE ([ID] = @ID)"
);
Now it's a case of altering the sql in the migration from a delete to an update. It wouldn't be too arduous to do it with text/replace but wouldn't it be cool if we could change the template used to generate the CreateStoredProcedure calls?....
回答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;
来源:https://stackoverflow.com/questions/18985295/ef5-how-to-alter-the-default-delete-function-to-implement-my-own