繁体   English   中英

实体框架dbcontext C#的垃圾收集

[英]Garbage collection for Entity Framework dbcontext c#

只是想知道我是否在这里正确放置了dbcontext对象,还是应该使用using块?

public class RepoBankAccount : IBankAccount
{
    private AppDbContext db = null;

    public RepoBankAccount()
    {
        this.db = new AppDbContext();
    }

    public RepoBankAccount(AppDbContext db)
    {
        this.db = db;
    }

    public IEnumerable<BankAccount> ViewAllBankAccount()
    {
        return db.BankAccounts.ToList();   
    }

    public BankAccount ViewBankAccount(long accountNumber)
    {
        return db.BankAccounts.Where(b => b.AccountNumber.Equals(accountNumber)).SingleOrDefault();            
    }


    public void DeleteBankAccount(BankAccount bankAccount)
    {
        db.BankAccounts.Remove(bankAccount);
        Save();
    }

    public void InsertBankAccount(BankAccount bankAccount)
    {
        db.BankAccounts.Add(bankAccount);
        Save();
    }        

    public void Save()
    {
        try
        {
            db.SaveChanges();
        }
        catch(Exception ex)
        {
            System.Console.WriteLine("Error:" + ex.Message);
        }
        finally
        {
            if(db != null)
            db.Dispose();
        }

    }        
}

我读到我不应该从

https://softwareengineering.stackexchange.com/questions/359667/is-it-ok-to-create-an-entity-framework-datacontext-object-and-dispose-it-in-a-us

但是在一些示例代码中,我也注意到了这个脚手架代码,但是并不太清楚它是如何独立完成工作的。

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }

DbContext被设计为短命的。 最初的初始化和DbContext的使用会带来解决实体映射的费用增加,但除此之外,上下文可以限定为单个调用或一组调用。 您的代码可以正常工作,并且只要处置您的存储库,dbContext就会被清理。 这种方法存在一些缺陷,尽管随着产品的成熟,很容易忘记处理某些东西,而且这些DbContext可以长期保存很多内存。

为了避免实体与其DbContext断开连接的问题,实体永远不应离开其DbContext的范围。 如果是这样,例如,如果触发了惰性加载,就会遇到错误。

例如,假设我在Controller中有一个方法或执行以下操作的方法:(注意:我不提倡将Entities返回到视图中,但是例如,为了...)

public ActionResult View(long accountNumber)
{
   BankAccount bankAccount;
   using (var repo = new RepoBankAccount())
   {
      bankAccount = repo.ViewBankAccount(accountNumber);
   }
   return new View(bankAccount);
}

回购将被处置,并且如果银行帐户没有参考资料,或者渴望加载所有参考资料,则此调用可以正常进行。 但是,如果存在延迟加载调用,则控制器方法将失败,因为已处置了与银行帐户关联的DbContext。

这可以通过确保返回发生在using块的范围内来补偿:

public ActionResult View(long accountNumber)
{
   using (var repo = new RepoBankAccount())
   {
      BankAccount bankAccount = repo.ViewBankAccount(accountNumber);
      return new View(bankAccount);
   }
}

为了避免此类问题,通常最好创建POCO视图模型类,以在实体的DbContext范围内进行填充,然后返回这些视图模型。 没有意外的懒惰负载命中等。

当您希望协调诸如跨实体的更新之类的事情以确保更新被一起提交或回滚时,这种情况真正开始崩溃的地方。 您的每个repo类都将具有单独的DbContext实例。

解决此问题的第一个默认方法是依赖注入和控制反转,尤其是IoC容器,例如Autofac ,Unity,Ninject或Castle Windsor。 使用这些,您可以使您的存储库类接受对DbContext的依赖关系,并且它们可以在整个生命周期内限定单个依赖关系实例。 (例如,按照HTTP请求),这样,将为单个会话调用中所有存储库的引用提供相同的DbContext实例。 调用SaveChanges()将尝试提交所有未决的更改。

更好的模式是“工作单元”模式,其中DbContext的范围移到存储库之外,并且每个存储库都提供了对DbContext的引用,也可以找到它。 (类似于IoC模式的工作方式)UoW模式的优势在于,您可以将提交/回滚的控制权移交给存储库的使用者,因此我提倡使用Mehdime的DbContextScope,因为它不需要传递对DashContextScope的引用。 UOW /的DbContext。 Mehdime DbContextScopeEF6原始githubEFCore支持的端口

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM