[英]EF 5 Conditional Mapping
我在我的MVC應用程序中使用EF 5數據庫第一種方法。 我的所有表都使用一個名為Deleted的字段,這是一個標記記錄被刪除的布爾字段。
我試圖擺脫每次查詢我的數據庫時必須檢查Deleted == false的要求。 這種非常簡單的方法是在edmx文件中使用條件映射,其中EF始終返回未刪除的數據。 這一切都很好。
但是,這個條件映射的問題在於,當我想允許用戶從地址簿中刪除例如地址的某些記錄時,我無法訪問EF中的刪除字段,因為我在條件映射中使用它,因此我必須尋找另一個允許用戶刪除記錄的選項。
我想的方法是創建一個處理刪除查詢的存儲過程,並在我想刪除記錄時調用它。
有沒有更好的方法呢? 是否可以使刪除字段可訪問,即使它在條件映射中使用?
我有一個有效的解決方案,可以幫助實體框架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;
}
這就是我以前的做法。 可能與EF5中的Database First方法無關,但我現在已經開始在存儲過程中執行此操作。 EF6 Code First在遷移文件中生成CreateStoredProcedure
調用。 我用this.CreateDeleteProcedure("dbo.Foo_Delete", "[dbo].[Foos]");
替換它們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)
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.