传递到另一个`using'块时DbContext过早地处理

时间:2016-08-27 04:27:30

标签: c# .net entity-framework

我有一个功能,需要在多个地方使用的有效UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"main" bundle:nil]; MyprofileQRsViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"SBMyprofileDetails"]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; [navController setViewControllers: @[rootViewController] animated: YES]; [self.revealViewController setFrontViewController:navController]; [self.revealViewController setFrontViewPosition: FrontViewPositionRight animated: YES]; 。在某些地方,dbContext已经存在,所以我将其传入并使用它,如果它:

DbContext

有没有办法让这个模式工作,或者我应该只需要public void DoStuff(){ using (var db = new dbContext()){ DoThings(db); db.SaveChanges(); // breaks, context was disposed } } public void DoThings(DbContext optionalContext = null){ using (var db = optionalContext ?? new dbContext()){ DoInternalThings(db); } } 并从调用函数中调出上下文?因为那时我最终得到了一堆:

optionalContext

4 个答案:

答案 0 :(得分:2)

您不应该处置传递给函数的对象,因为您不拥有它并且不控制它的生命周期。是的,在调用函数中启动上下文并创建所需的上下文,这取决于如何以美观和方便的方式设计它。

答案 1 :(得分:0)

您不需要为内部函数创建另一个上下文。如果已存在,则使用已创建的上下文,否则创建一个新函数,如下所示。

 public void DoStuff(){
         using (var db = new dbContext()){
             DoThings(db);
             db.SaveChanges();
         }
      }

    public void DoThings(DbContext db){
        if (db =null){
           using (var db = new dbContext()){
              DoInternalThings(db);
             }
           }else{
              DoInternalThings(db);
           }       
      }

有关实体框架团队项目经理的DbContextUsing声明行为的良好解释。

Rowan Miller(MSFT)

  

DbContext的默认行为是底层连接   需要时自动打开,否则关闭   需要更久。例如。当您执行查询并迭代查询时   结果使用“foreach”,调用IEnumerable.GetEnumerator()   会导致连接被打开,而以后则没有   更多结果可用,“foreach”将负责调用Dispose on   枚举器,它将关闭连接。以类似的方式,a   调用DbContext.SaveChanges()之前会打开连接   将更改发送到数据库并在返回之前将其关闭。

     

鉴于此默认行为,在许多实际案例中,它是无害的   离开上下文而不处理它只是依赖垃圾   采集。

     

那就是说,我们的示例代码总是有两个主要原因   使用“使用”或以其他方式处理上下文:

     
      
  1. 默认的自动打开/关闭行为相对容易覆盖:您可以控制何时打开连接并且   通过手动打开连接关闭。一旦你开始这样做   在你的代码的某些部分,然后忘记了上下文   变得有害,因为你可能会泄漏开放的连接。

  2.   
  3. DbContext按照推荐的模式实现IDiposable,其中包括公开虚拟保护的Dispose方法   派生类型可以覆盖,例如,如果需要聚合其他   非托管资源进入上下文的生命周期。

  4.   

以下是它的原始文章:Do I always have to call Dispose() on my DbContext objects

答案 2 :(得分:0)

您可以传输dbcontext,但为什么?为什么不喜欢

public enum thingsToDo  {myStuff, yourStuff, otherStuff };
    public void doThings(thingsToDo whatToDo)
    {
        using (SqlConnection conn = new SqlConnection(""))
        {
            switch (whatToDo)
            {
                case thingsToDo.myStuff:
                    //this is what's indside the USING statement in doStuff
                    break;
                case thingsToDo.yourStuff:
                    //this is what's inside the USING statement in yourStuff
                    break;
                case thingsToDo.otherStuff:
                    //this is in method 3
                    break;
            }

            db.SaveChanges();
        }
    }

然后是以下一项或全部:

doThings(thingsToDo.myStuff); doThings(thingsToDo.otherStuff);doThings(thingsToDo.yourStuff);

答案 3 :(得分:0)

根据我的想法,您的代码正在执行要求执行的操作。如果您使用"使用"然后它会在它结束时调用dispose方法。我还建议您的代码设计有问题。如果正在其他地方创建Dbcontext,那么它的生命周期也由创建它的其他函数控制。

这里的问题是第二次使用不知道那里已经有一个使用块。这就是编译器的设计方式。我也同意@Sampath代码。