2013-09-01 42 views
1

我写一个asp.net应用mvc4和我使用实体框架5.我的每一个实体的检索OriginalValues有像EnteredByEnteredOnLastModifiedByLastModifiedOn领域。无法在实体框架5

我想通过使用SavingChanges事件来自动保存它们。下面的代码已经从众多博客放在一起,SO answeres等

public partial class myEntities : DbContext 
{ 
    public myEntities() 
    {    
     var ctx = ((IObjectContextAdapter)this).ObjectContext; 
     ctx.SavingChanges += new EventHandler(context_SavingChanges); 
    } 

    private void context_SavingChanges(object sender, EventArgs e) 
    { 

     ChangeTracker.DetectChanges(); 

     foreach (ObjectStateEntry entry in 
       ((ObjectContext)sender).ObjectStateManager 
        .GetObjectStateEntries 
        (EntityState.Added | EntityState.Modified)) 
     {   
      if (!entry.IsRelationship) 
      { 
       CurrentValueRecord entryValues = entry.CurrentValues;    

       if (entryValues.GetOrdinal("LastModifiedBy") > 0) 
       { 
        HttpContext currContext = HttpContext.Current; 
        string userName = ""; 
        DateTime now = DateTime.Now; 

        if (currContext.User.Identity.IsAuthenticated) 
        { 
         if (currContext.Session["userId"] != null) 
         { 
          userName = (string)currContext.Session["userName"]; 
         } 
         else 
         { 
          userName = currContext.User.Identity.Name; 
         } 
        } 

        entryValues.SetString(
         entryValues.GetOrdinal("LastModifiedBy"), userName); 
        entryValues.SetDateTime(
         entryValues.GetOrdinal("LastModifiedOn"), now); 

        if (entry.State == EntityState.Added) 
        { 
         entryValues.SetString(
          entryValues.GetOrdinal("EnteredBy"), userName); 
         entryValues.SetDateTime(
          entryValues.GetOrdinal("EnteredOn"), now); 
        } 
        else 
        {     
        string enteredBy = 
        entry.OriginalValues.GetString(entryValues.GetOrdinal("EnteredBy")); 
        DateTime enteredOn = 
entry.OriginalValues.GetDateTime(entryValues.GetOrdinal("EnteredOn")); 

         entryValues.SetString(
         entryValues.GetOrdinal("EnteredBy"),enteredBy); 
         entryValues.SetDateTime(
         entryValues.GetOrdinal("EnteredOn"), enteredOn); 

        } 
       } 
      } 
     } 
    } 
} 

我的问题是entry.OriginalValues.GetString(entryValues.GetOrdinal("EnteredBy"))entry.OriginalValues.GetDateTime(entryValues.GetOrdinal("EnteredOn"))没有返回原来的值,而是电流值是null。我测试了实体中的其他字段,并且它们返回了在html表单中输入的当前值。

如何在此处获取原始值?

+0

你如何更新实体?你是从数据库上下文中首先检索它们,然后使用控制器中收到的值更新它的属性? –

+0

我不知道如何回答你的问题。我正在使用脚手架来做到这一点。 – unlimit

回答

3

我认为问题可能是您使用模型联编程序提供的实例作为控制器方法的输入,因此EF并不知道任何有关该实体及其原始状态的信息。您的代码可能会是这样:

public Review Update(Review review) 
{ 
    _db.Entry(review).State = EntityState.Modified; 
    _db.SaveChanges(); 
    return review; 
} 

在这种情况下,EF一无所知正在被保存在Review实例。它信任你并将其设置为已修改,因此它将把它的所有属性保存到数据库中,但它不知道该实体的原始状态\值。

检查名为的实体状态以及this tutorial的Attach和SaveChanges方法。您还可以检查this article的第一部分,该部分显示了EF如何不知道原始值,并将更新数据库中的所有属性。

由于EF需要了解原始属性,因此可以先从数据库加载实体,然后使用控制器中收到的值更新其属性。事情是这样的:

public Review Update(Review review) 
{ 
    var reviewToSave = _db.Reviews.SingleOrDefault(r => r.Id == review.Id); 
    //Copy properties from entity received in controller to entity retrieved from the database 
    reviewToSave.Property1 = review.Property1; 
    reviewToSave.Property2 = review.Property2; 
    ... 

    _db.SaveChanges(); 
    return review; 
} 

这样做的好处,只有修改的属性将发送,并在数据库中更新,并且您的观点和看法模型不需要暴露在你的业务对象各个领域,只有那些可以由用户更新。 (打开viewModel和models \ business对象的不同类的门)。显而易见的缺点是你会对数据库造成额外的打击。

上面引用的教程中提到的另一个选项是让您以某种方式(隐藏字段,会话等)保存原始值,并在保存时使用原始值以未修改的方式将实体附加到数据库上下文。然后用编辑的字段更新该实体。但是我不会推荐这种方法,除非你真的需要避免额外的数据库命中。

希望有帮助!

+0

啊,谢谢。我也对缺乏适当人群的原始价值感到困惑。当我更改我的保存以加载,然后将传入的实体的属性映射到数据库条目上时,原始值正确填充。 – stimms

2

当我试图审计记录一个实体的Modified值时,我遇到了类似的问题。

事后证明,ModelBinder无法访问原始值,因此收到的Model缺少正确的信息。我通过使用克隆当前值的函数修复了我的问题,重新对对象,然后重置当前值。

void SetCorrectOriginalValues(DbEntityEntry Modified) 
    { 
     var values = Modified.CurrentValues.Clone(); 
     Modified.Reload(); 
     Modified.CurrentValues.SetValues(values); 
     Modified.State = EntityState.Modified; 
    } 

您可以获取对DbEntityEntry访问虽然变更跟踪,或从上下文的入口函数。