我在那里,好消息是,如果您不想的话,您不必放弃Entity Framework。 坏消息是您必须自己更新数据库。 这并不像看起来那么难。 我目前正在使用EF 5,但计划使用EF6。我不明白为什么这对于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,包括锁定提示并包含事务级别,这是我们想要的方式。 如果用户也将数字字段更新为2,则我们也将数字字段从刚设置为nfield = 10更改为nfield = nfield + 2(在TSQL中),也避免了并发问题。
一旦有人开始编辑您的实体,您将无法锁定SQL,但是我也看不到如何通过存储过程来实现。
总而言之,我花了大约2天的时间才能完成所有准备工作。