我正在使用MVC4和实体框架5创建一个应用程序。我该如何实现它? 我环顾四周,发现我需要覆盖SaveChanges。
有没有人对此有任何示例代码?我正在使用代码第一种方法。
例如,我保存数据的方式如下,
public class AuditZoneRepository : IAuditZoneRepository
{
private AISDbContext context = new AISDbContext();
public int Save(AuditZone model, ModelStateDictionary modelState)
{
if (model.Id == 0)
{
context.AuditZones.Add(model);
}
else
{
var recordToUpdate = context.AuditZones.FirstOrDefault(x => x.Id == model.Id);
if (recordToUpdate != null)
{
recordToUpdate.Description = model.Description;
recordToUpdate.Valid = model.Valid;
recordToUpdate.ModifiedDate = DateTime.Now;
}
}
try
{
context.SaveChanges();
return 1;
}
catch (Exception ex)
{
modelState.AddModelError("", "Database error has occured. Please try again later");
return -1;
}
}
}
答案 0 :(得分:0)
无需覆盖SaveChanges。
你可以
根据您的代理方法,可能需要触发Context.ChangeTracker.DetectChanges();
//
然后在保存之前分析上下文。 然后,您可以...将更改日志添加到CURRENT工作单元。 因此,日志将保存在一个COMMIT事务中。 或者按照您认为合适的方式处理它。 但是同时保存更改日志。确保它是一个交易。
分析上下文示例: 我有一个简单的工具,转储上下文内容以调试输出,所以在调试器中我可以使用立即窗口来检查内容。例如 您可以将其用作启动器来准备CHANGE日志。 在调试器即时窗口中尝试它。我在Context类上有完全转储。
示例立即窗口调用。 UoW.Context.FullDump();
public void FullDump() {
Debug.WriteLine("=====Begin of Context Dump=======");
var dbsetList = this.ChangeTracker.Entries();
foreach (var dbEntityEntry in dbsetList)
{
Debug.WriteLine(dbEntityEntry.Entity.GetType().Name + " => " + dbEntityEntry.State);
switch (dbEntityEntry.State)
{
case EntityState.Detached:
case EntityState.Unchanged:
case EntityState.Added:
case EntityState.Modified:
WriteCurrentValues(dbEntityEntry);
break;
case EntityState.Deleted:
WriteOriginalValues(dbEntityEntry);
break;
default:
throw new ArgumentOutOfRangeException();
}
Debug.WriteLine("==========End of Entity======");
}
Debug.WriteLine("==========End of Context======");
}
private static void WriteCurrentValues(DbEntityEntry dbEntityEntry)
{
foreach (var cv in dbEntityEntry.CurrentValues.PropertyNames)
{
Debug.WriteLine(cv + "=" + dbEntityEntry.CurrentValues[cv]);
}
}
private static void WriteOriginalValues(DbEntityEntry dbEntityEntry)
{
foreach (var cv in dbEntityEntry.OriginalValues.PropertyNames)
{
Debug.WriteLine(cv + "=" + dbEntityEntry.OriginalValues[cv]);
}
}
}
编辑:获取更改
我使用这个例程来获取chnages ......
public class ObjectPair {
public string Key { get; set; }
public object Original { get; set; }
public object Current { get; set; }
}
public virtual IList<ObjectPair> GetChanges(object poco) {
var changes = new List<ObjectPair>();
var thePoco = (TPoco) poco;
foreach (var propName in Entry(thePoco).CurrentValues.PropertyNames) {
var curr = Entry(thePoco).CurrentValues[propName];
var orig = Entry(thePoco).OriginalValues[propName];
if (curr != null && orig != null) {
if (curr.Equals(orig)) {
continue;
}
}
if (curr == null && orig == null) {
continue;
}
var aChangePair = new ObjectPair {Key = propName, Current = curr, Original = orig};
changes.Add(aChangePair);
}
return changes;
}
编辑2如果必须使用内部对象跟踪。
var context = ???// YOUR DBCONTEXT class
// get objectcontext from dbcontext...
var objectContext = ((IObjectContextAdapter) context).ObjectContext;
// for each tracked entry
foreach (var dbEntityEntry in context.ChangeTracker.Entries()) {
//get the state entry from the statemanager per changed object
var stateEntry = objectContext.ObjectStateManager.GetObjectStateEntry(dbEntityEntry.Entity);
var modProps = stateEntry.GetModifiedProperties();
Debug.WriteLine(modProps.ToString());
}
我反编译了EF6。获得修改确实是使用私有位数组来跟踪具有的字段 已经改变了。
// EF decompiled source..... _modifiedFields is a bitarray
public override IEnumerable<string> GetModifiedProperties()
{
this.ValidateState();
if (EntityState.Modified == this.State && this._modifiedFields != null)
{
for (int i = 0; i < this._modifiedFields.Length; ++i)
{
if (this._modifiedFields[i])
yield return this.GetCLayerName(i, this._cacheTypeMetadata);
}
}
}