2011-08-22 46 views
1

我最近与实体框架开始的MVC项目我做得到与技术的夹具和我有几个问题:..实体框架 - 建议和最佳实践

我第一个是这个,这是我的一个实体保存代码 - 这是最好的方式..它看起来有点涉嫌我..

public bool SavePrank(PrankDefinition prank) 
    { 

     if (prank == null) 
      throw new ArgumentNullException("prank"); 

     if (prank.ID == 0) 
     { 
      DataBase.Pranks.Add(prank); 
      DataBase.SaveChanges(); 
     } 
     else 
     { 
      DataBase.Pranks.Attach(prank); 
      DataBase.Entry(prank).State = EntityState.Modified; 
      DataBase.SaveChanges(); 
     } 

     return true; 

    } 

香港专业教育学院还得到这个代码,获取最新版本的实体..

public List<PrankDefinition> GetPranks() 
    { 
     List<PrankDefinition> pranks = DataBase.Pranks.Where(p => p != null).ToList(); 

     foreach (PrankDefinition prankDef in pranks) 
     { 
      DataBase.Entry(prankDef).Reload(); 
     } 

     return pranks; 
    } 

iive不得不调用实体的重新加载的原因是因为当另一个客户端正在使用该项目时 - 实体的更改不会立即反映出来(这很关键)。我的问题是 - 有没有更好的方法来做到这一点?有什么我可以附加到Where方法来获取最新版本?

我的上下文 - 如果它可以帮助..

public static DataContext DataBase 
    { 
     get 
     { 
      if (HttpContext.Current != null &&   HttpContext.Current.Session["DataBase"]== null) 
      { 
       HttpContext.Current.Session["DataBase"] = new DataContext(); 
      } 

      return HttpContext.Current.Session["DataBase"] as DataContext; 
     } 
     set 
     { 
      if (HttpContext.Current != null) 
       HttpContext.Current.Session["DataBase"] = value; 
     } 
    } 

任何帮助将是非常美妙!

编辑:更新到数据文本

这会是一个更好的实施的DataContext的?

public static DataContext DataBase 
    { 
     get { return new DataContext(); } 
    } 

欢呼声。 ste。

回答

4

只是几句话:

  • 在我看来SaveChanges完成的工作单位,不属于单个存储库的方法,如SavePrank。我可能更喜欢这样的模式:

    InsertOrUpdatePrank(prank); // = SavePrank without SaveChanges 
    ModifyPerhapsSomeOtherEntity(otherEntity); 
    SetPerhapsRelationshipBetweenPrankAndOtherEntity(prank, otherEntity); 
    // ... more ... 
    DataBase.SaveChanges(); 
    

    这样,所有更改都写入到单个事务中的数据库。

  • 你在哪里处置你的上下文?如果您实例化并将其存储在会话中,但不要在代码中明确地处理上下文,则该上下文将存在于多个请求中。这是一个大问题的潜在根源,因为当您处理新的请求时,您的上下文可能仍包含来自旧请求的实体。例如:如果prankID = 123在来自同一用户的两个后续请求(在同一会话中)中更新两次DataBase.Pranks.Attach(prank)将引发异常,因为来自先前具有相同ID的请求的旧恶作剧已被附加到上下文。在Web应用程序中,上下文永远不应该比单个请求活得更长,以避免出现像以上这样的问题。

  • 如果您为每个请求处理上下文,我不再需要“重新加载”实体。无论如何,您必须从数据库加载实体,因为每个上下文都是新的,并且在您输入操作时为空。所以,没有什么可以重新加载。无论如何,当你运行你的查询时,你会从数据库中获得最新版本的实体。

  • Where(p => p != null)是没有意义的。要获取所有行,你可以这样写:

    List<PrankDefinition> pranks = DataBase.Pranks.ToList(); 
    
+0

感谢所有队友的建议。 SavePrank方法是非常自包含的,所以这就是为什么我在那时使用SaveChanges - 这仍然是不正确的?..另请参阅更新上下文。 – Steoates

+0

@Stephen:不,在这种特殊情况下并不正确。这就是如何在更复杂的情况下处理SaveChanges的问题。在我看来,将SaveChanges保存在存储库之外是更好的方法。您在问题中的更新很糟糕:您每次访问“数据库”属性时都会创建一个新的上下文。 – Slauma