【问题标题】:Which is the better, an instance variable or a local variable for an EF context?EF 上下文的实例变量或局部变量哪个更好?
【发布时间】:2013-06-02 12:30:13
【问题描述】:

我知道标题看起来有点糟糕:) 但我不知道如何解释我的问题..

这对我来说通常是一个基本问题,但我不知道答案..

我正在编写一个服务器应用程序,它使用 eneter 库进行客户端-服务器通信,并且它还有一个 DAL 从数据库获取数据。作为一个服务器应用程序,它总是需要与数据库通信,所以我不知道哪种方式更有效。 (大约,最多 50 个客户端将连接到服务器)

我正在使用实体框架并从我的 mysql 数据库中创建了一个模型。

第一个代码在这里

    private MyEntities ent;

    public DbHelper()
    {
     ent = new MyEntities();
    }

   void Foo()
  { 
       ent.Mytable.where......
       ....

  }

第二类代码是

    void Foo()
    {
        using (MyEntities ent = new MyEntities())
        {
            ent.Mytable.where...
        }

    }

我可以使用 using 语句或为 dal 类创建一个 global 实例变量并将其用于每个函数..?

【问题讨论】:

  • 那不是全局变量(甚至不是static)。
  • @HenkHolterman,我想你明白我的意思..我可以在课堂上使用这个变量..所以如果需要改变,你可以做到

标签: c# entity-framework idisposable using-statement


【解决方案1】:

更好的是,在 DAL 类上实现 IDisposable:

public sealed class MyDal implements IDisposable
{
    private MyEntities ent = new MyEntities();

    void Foo()
    { 
       ent.Mytable.where......
       ....

    }

    public void Dispose()
    {
        ent.Dispose();
    }
}

那么……

using(var dal = new MyDal())
{
    dal.Foo();
    //....
}

阅读here,了解为什么我的 IDisposable 被密封。

【讨论】:

  • 谢谢你的回答,我应该像这样使用 using(var dal = new MyDal()) 还是我的 dal 是一个局部变量?
  • @ertan2002 很难理解你在问什么。 using 语句中的变量一个局部变量。
  • 啊抱歉我写错了:我的意思是 mydal 类的实例变量.. 像 MyDal dal;
  • 您在 DAL 类中编写数据访问代码,在需要进行数据访问的地方,将 MyDal 实例包装在 using 语句中。这意味着当您完成数据访问时,MyDal 持有的资源会得到整齐的处置。您是否需要您的 MyDal 拥有更长的寿命?
  • 我知道你在说什么,是的,如果我创建一个 mydal 类的实例变量而不是 using 语句更好吗?因为我的应用程序将是服务器,我怀疑总是创建一个 mydal 的局部变量,并且在处理后它会更好..只需从 mydal 创建实例并始终使用它..看起来更合乎逻辑吗?
【解决方案2】:

从性能的角度来看,这并不重要。与实际的数据库交互相比,创建上下文实例是一个非常快的操作。

但是,无论如何,您都应该释放创建的上下文,因为它将数据库连接作为本机资源。

如果您想在DbHelper 类中使用上下文成员,则该类应实现IDisposable,以便您可以在DbHelper 实例本身被释放时释放上下文:

public class DbHelper : IDisposable
{
    private MyEntities ent;

    public DbHelper()
    {
        ent = new MyEntities();
    }

    public void Foo()
    {
        //...
    }

    public void Bar()
    {
        //...
    }

    public void Dispose() // implementation of IDisposable
    {
        ent.Dispose();
    }
}

您可以在 using 块中使用此类:

using (var helper = new DbHelper())
{
     helper.Foo();
     helper.Bar();
} // helper and helper.ent gets disposed now

【讨论】:

  • 如果你没有实现完整的 IDisposable 模式,你的类应该sealed
  • 谢谢你的回答 slauma,我问你同样的问题,我需要使用 using(var helper ...()) 代替 dbhelper 类的位置变量吗?我无法决定哪个更好
  • @Spender sealed 不是一次性模式的要求 - protected virtual Dispose(bool disposing) 是多态一次性类型的规范 - 尽管这可能是您所说的“完全一次性模式”的意思 -在这种情况下,我同意。也许有一些 GC.SuppressFinalize。
  • @MarcGravell,当然,这不是必需的,但如果您没有为子类提供正确处理的工具,那么密封是一个非常好的主意。
【解决方案3】:

这取决于存在哪些其他方法以及它们的作用。如果您想使用 ORM 进行更改并保留这些更改,您将需要创建对象的数据上下文。此外,如果您希望身份管理器在您两次查询同一事物时为您提供相同的对象实例,您将需要使用相同的数据上下文 - 所以您需要将其放在手边。最后,如果该类型使用延迟加载并且您希望它能够工作 - 如果您已经处理了数据上下文,那将无法正常工作。

但是,如果您只想对数据进行只读访问,而不需要更改跟踪、延迟加载或身份管理:请立即处理。并且也许考虑像 micro-ORM 这样根本不具备这些功能的东西(特意做到最小且快速)。

【讨论】:

    【解决方案4】:

    这两种方法在变更跟踪的范围方面非常不同。如果两者都能正常工作,请确保使用WithNoTracking

    您可以像在第一个代码中一样为您的实体创建一个成员变量。但是因为你不能在它周围写一个using(){} 语句,所以包含类应该是IDisposable。然后消费类应该在using(){} 中使用它。

    【讨论】:

    • 感谢您编辑我的标题和答案,我将使用更改跟踪和其他东西,我还将使用通用存储库设计模式..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多