EF 5条件映射 [英] EF 5 Conditional Mapping
问题描述
我用在我的MVC应用程序EF 5数据库第一种方法。我所有的表使用了一个名为删除字段是一个布尔字段标记记录被删除。
I'm using EF 5 Database first approach in my MVC application. all of my tables uses a Field called Deleted which is a boolean field to mark a record is deleted.
我试图摆脱虚假每次不必检查删除==的要求,我查询我的数据库。这样做的非常简单的方法是使用一个条件映射在EDMX文件,其中EF始终返回未删除的数据。这一切都很好。
I'm trying to get rid of the requirement of having to check Deleted == false every time I query my database. The very straightforward way of doing this is to use a conditional mapping in the edmx file where EF always return data that are not deleted. That's all good.
但这样做的条件映射的问题是,当我想允许用户从自己的地址簿中删除如地址记录一些我没有访问来自EF删除字段正如我在有条件的用它映射,所以我必须去寻找另一个选项,允许用户删除记录。
But the problem of doing this condition mapping is that, when I want to allow the user to delete some record for e.g Address from their address book I don't have access to Delete field from EF as I used it in the conditional mapping and therefore I have to look for another option to allow user to delete a record.
我想的方法是创建一个存储过程的处理删除查询,并调用它,当我想要删除的记录。
The way I thought is to create a stored proc that handle the delete query and call it when I want to delete the record.
是否有这样做的更好的办法?是否有可能使其在有条件的映射中使用的删除字段访问甚至?
Is there a better way of doing this? Is it possible to make the Delete field accessible even it is used in the conditional mapping?
推荐答案
我有实体框架$ C软删除$ C首先这可能会有帮助。
I have a working solution for Soft Delete in Entity Framework Code First that may help.
的关键是,你增加一个鉴别器要能软删除每一个模型。在code首先是这样完成的:
The key is that you add a discriminator to every model that you want to be able to soft delete. In code first that is done like this:
modelBuilder.Entity<富方式>()地图(M =方式> m.Requires(请将isDeleted)的HasValue(假));
这使得它无形的环境,因此,你必须使用SQL做删除。
This makes it invisible to the context and therefore you have to do the deletes using sql.
如果这是你的数据库有条件映射相当于一则修改SQL的一种方式是重写的SaveChanges并从那里运行SQL语句:
If this is the equivalent of your "conditional mapping" in Database First then one way to modify the sql is to override SaveChanges and run sql from there:
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数据库第一的方针,但现在我已经搬到了在存储过程中这样做。 EF6 code首先生成 CreateStoredProcedure
调用迁移的文件。我与 this.CreateDeleteProcedure取代这些(dbo.Foo_Delete,[DBO] [FOOS]。);
- 这是我自己的扩展方法的调用:
That is the way I used to do it. Probably irrelevant to your Database First approach in EF5, but I have now moved to doing it in stored procedures. EF6 Code First generates CreateStoredProcedure
calls in Migration files. I replace these with this.CreateDeleteProcedure("dbo.Foo_Delete", "[dbo].[Foos]");
- which is a call to my own extension method:
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)
);
}
}
这篇关于EF 5条件映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!