字段成员与方法变量?

2024-01-28

最近我一直在思考类字段成员和方法变量之间的性能差异。我的确切意思是在下面的例子中:

假设我们有一个DataContext对象为Linq2SQL

class DataLayer
{
    ProductDataContext context = new ProductDataContext();

    public IQueryable<Product> GetData()
    {
       return context.Where(t=>t.ProductId == 2);
    }
}

在上面的例子中,上下文将存储在堆中,GetData方法执行后,方法变量将从堆栈中删除。

因此,让我们检查以下示例来进行区分:

class DataLayer
{
    public IQueryable<Product> GetData()
    {
       ProductDataContext context = new ProductDataContext();
       return context.Where(t=>t.ProductId == 2);
    }
} 

(*1)所以好吧,我们首先知道的是如果我们定义ProductDataContext实例作为一个字段,我们可以在类中的任何地方访问它,这意味着我们不必一直创建相同的对象实例。

但是,假设我们正在讨论 Asp.NET,一旦用户按下提交按钮,发布数据就会发送到服务器,事件将被执行,发布的数据将通过上述方法存储在数据库中,因此很可能是同一个用户可以一个接一个地发送不同的数据。如果我在页面执行后正确地知道,终结器就会发挥作用并从内存(从堆)中清除内容,这意味着我们也会从内存中丢失实例变量,并且在另一篇文章之后,DataContext应为新的页面周期再次创建。

因此,向全班公开宣布这一点的唯一好处似乎就是上面的第一条文字。

还是还有别的什么?

提前致谢...

(如果我说的有误,请纠正我..)


当谈到按方法或按类实例创建对象之间的性能差异时,我不会太担心。然而,您似乎在这里错过了围绕 DataContext 类和一般工作单元模式的一些重要原则。

DataContext 类作为单个工作单元运行。因此,您创建一个 DataContext,创建对象,更新和删除对象,提交所有更改,然后处理 DataContext。您可以为每个请求创建多个 DataContext 类,每个(业务)事务一个。但在 ASP.NET 中,您永远不应该创建在 Web 请求后仍然存在的 DataContext。在请求期间创建的所有 DataContext 都应在请求结束时或之前释放。有两个原因。

首先,DataContext 有一个内部缓存,其中包含从数据库获取的所有对象。长时间使用 DataContext 会使其缓存无限增长,并且当数据库很大时可能会导致内存问题。 DataContext 还倾向于在可能的情况下从缓存中返回对象,从而使您的对象很快变得陈旧。由于这种陈旧性,对另一个 DataContext 或直接对数据库进行的任何更新和删除操作都可能会被忽视。

不缓存 DataContext 的第二个原因是它们不是线程安全的。最好将 DataContext 视为一个工作单元或(业务)事务。您创建了一堆新对象,将它们添加到 DataContext,更改其他一些对象,删除一些对象,完成后,调用 SubmitChanges。如果在该操作期间另一个请求在同一实例上调用 SubmitChanges,您就会失去事务的概念。当您允许代码执行此操作时,在最幸运的情况下,您的新对象将被持久化,并且您的事务将分为两个单独的事务。最坏的情况是,您的 DataContext 或其保留的对象处于无效状态,这可能意味着其他请求失败或无效数据进入您的数据库。这并不是不可能的情况,我见过如果开发人员为每个网站创建一个(静态)DataContext 的项目中会发生奇怪的事情。

考虑到这一点,让我们回到你的问题。虽然将 DataContext 定义为实例字段不是问题,但了解如何使用该字段很重要DataLayer班级。当你创建一个DataLayer每个请求或每个方法调用,你可能是安全的,但在这种情况下你不应该存储它DataLayer在静态场中。当您想要这样做时,您应该为每个方法调用创建一个 DataContext。

重要的是要知道它的设计是什么DataLayer类是。在您的代码中,您只向我们展示了一个查询方法。没有 CUD 方法。每个方法都应该是一个事务,还是要调用多个方法并调用 SaveChangesDataLayer然后?当您想要最后一个选项时,您需要存储DataContext作为实例字段,在这种情况下你应该实现IDisposable on the DataLayer。当每个方法都是其自己的事务时,您可以为每个方法创建一个 DataContext,并且应该将 DataContext 包装在 using 语句中。但请注意,当您从方法返回具有延迟加载属性的对象时,处置 DataContext 可能会导致问题。当 DataContext 被释放后,这些属性将无法再加载。Here https://stackoverflow.com/questions/2785506/linq-to-sql-web-application-best-practices/2786713#2786713有关于此的更有趣的信息。

正如您所看到的,我什至没有讨论两个选项中哪一个对性能更好,因为当解决方案给出不一致和不正确的结果时,性能并不重要。

我很抱歉我的回答很长:-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字段成员与方法变量? 的相关文章

随机推荐