Ami*_*ila 4 c# entity-framework asp.net-mvc-4
我在我的MVC应用程序中使用EF 5数据库第一种方法.我的所有表都使用一个名为Deleted的字段,这是一个标记记录被删除的布尔字段.
我试图摆脱每次查询我的数据库时必须检查Deleted == false的要求.这种非常简单的方法是在edmx文件中使用条件映射,其中EF始终返回未删除的数据.这一切都很好.
但是,这个条件映射的问题是,当我想允许用户从地址簿中删除例如地址的某些记录时,我无法访问EF中的删除字段,因为我在条件映射中使用它,因此我必须寻找另一个允许用户删除记录的选项.
我想的方法是创建一个处理删除查询的存储过程,并在我想要删除记录时调用它.
有没有更好的方法呢?是否可以使删除字段可访问,即使它在条件映射中使用?
Col*_*lin 14
我有一个工作解决方案,可以帮助实体框架Code First中的软删除.
关键是你要为每个你想要软删除的模型添加一个鉴别器.在代码中首先这样做:
modelBuilder.Entity<Foo>().Map(m => m.Requires("IsDeleted").HasValue(false));
这使得它对上下文不可见,因此您必须使用sql执行删除操作.
如果这相当于Database First中的"条件映射",那么修改sql的一种方法是覆盖SaveChanges并从那里运行sql:
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries()
.Where(p => p.State == EntityState.Deleted
&& p.Entity is ModelBase))//I do have a base class for entities with a single
//"ID" property - all my entities derive from this,
//but you could use ISoftDelete here
SoftDelete(entry);
return base.SaveChanges();
}
private void SoftDelete(DbEntityEntry entry)
{
var e = entry.Entity as ModelBase;
string tableName = GetTableName(e.GetType());
Database.ExecuteSqlCommand(
String.Format("UPDATE {0} SET IsDeleted = 1 WHERE ID = @id", tableName)
, new SqlParameter("id", e.ID));
//Marking it Unchanged prevents the hard delete
//entry.State = EntityState.Unchanged;
//So does setting it to Detached:
//And that is what EF does when it deletes an item
//http://msdn.microsoft.com/en-us/data/jj592676.aspx
entry.State = EntityState.Detached;
}
Run Code Online (Sandbox Code Playgroud)
这就是我以前的做法.可能与EF5中的Database First方法无关,但我现在已经开始在存储过程中执行此操作.EF6 Code First CreateStoredProcedure在迁移文件中生成调用.我用this.CreateDeleteProcedure("dbo.Foo_Delete", "[dbo].[Foos]");- 替换它们- 这是对我自己的扩展方法的调用:
public static class MigrationExtensions
{
internal static string DeleteSqlFormat
{
//I also hard delete anything deleted more than a day ago in the same table
get { return "DELETE FROM {0} WHERE IsDeleted = 1 AND DATEADD(DAY, 1, DeletedAt) < GETUTCDATE(); UPDATE {0} SET IsDeleted = 1, DeletedAt = GETUTCDATE() WHERE ID = @ID;"; }
}
internal static void CreateDeleteProcedure(this DbMigration migration, string procName, string tableName)
{
migration.CreateStoredProcedure(
procName,
p => new
{
ID = p.Int(),
},
body:
string.Format(MigrationExtensions.DeleteSqlFormat, tableName)
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2771 次 |
| 最近记录: |