我在那里,好消息是如果你不想放弃实体框架,你不必放弃。坏消息是您必须自己更新数据库。这并不像看起来那么难。我目前正在使用 EF 5,但计划转到 EF 6。我不明白为什么这仍然不适用于 EF 6。
首先是在 DbContext 的构造函数中将其转换为 IObjectContextAdapter 并获得对 ObjectContext 的访问。我为此创建了一个属性
public virtual ObjectContext ObjContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
一旦您订阅了 SavingChanges 事件 - 这不是我们的确切代码,有些内容会从其他方法中复制出来并重做。这只是让您了解您需要做什么。
ObjContext.SavingChanges += SaveData;
private void SaveData(object sender, EventArgs e)
{
var context = sender as ObjectContext;
if (context != null)
{
context.DetectChanges();
var tsql = new StringBuilder();
var dbParams = new List<KeyValuePair<string, object>>();
var deletedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
foreach (var delete in deletedEntites)
{
// Set state to unchanged - so entity framework will ignore
delete.ChangeState(EntityState.Unchanged);
// Method to generate tsql for deleting entities
DeleteData(delete, tsql, dbParams);
}
var addedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added);
foreach (var add in addedEntites)
{
// Set state to unchanged - so entity framework will ignore
add.ChangeState(EntityState.Unchanged);
// Method to generate tsql for added entities
AddData(add, tsql, dbParams);
}
var editedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
foreach (var edit in editedEntites)
{
// Method to generate tsql for updating entities
UpdateEditData(edit, tsql, dbParams);
// Set state to unchanged - so entity framework will ignore
edit.ChangeState(EntityState.Unchanged);
}
if (!tsql.ToString().IsEmpty())
{
var dbcommand = Database.Connection.CreateCommand();
dbcommand.CommandText = tsql.ToString();
foreach (var dbParameter in dbParams)
{
var dbparam = dbcommand.CreateParameter();
dbparam.ParameterName = dbParameter.Key;
dbparam.Value = dbParameter.Value;
dbcommand.Parameters.Add(dbparam);
}
var results = dbcommand.ExecuteNonQuery();
}
}
}
为什么我们在更新后将实体设置为未修改,因为你可以这样做
var changed properties = edit.GetModifiedProperties();
获取所有已更改属性的列表。由于所有实体现在都标记为未更改,因此 EF 不会向 SQL 发送任何更新。
您还需要处理从实体到表以及从属性到字段的元数据。这并不难做到,但弄乱元数据确实需要一些时间来学习。有时我仍然在挣扎。我将所有这些重构到一个 IMetaDataHelper 接口中,在其中我将它传递给实体类型和属性名称以获取表和字段 - 同时缓存结果,因此我不必一直查询元数据。
最后,tsql 是一个批处理,它包含我们想要的所有 T-SQL,带有锁定提示并包含事务级别。我们还将数字字段从仅设置为 nfield = 10 更改为在 TSQL 中为 nfield = nfield + 2 如果用户将它们更新为 2 以避免并发问题。
一旦有人开始编辑您的实体,您就不会锁定 SQL,但我不知道您如何使用存储过程来获得它。
总而言之,我花了大约 2 天的时间来为我们完成这一切。