现场成员与方法变量?

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

假设我们有一个Linq2SQLDataContext对象

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

在上面的示例中,上下文将存储在堆中,并且在执行Method之后将从Stack中删除GetData方法变量。

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

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

(* 1)所以我们知道的第一件事就是如果我们将ProductDataContext实例定义为一个字段,我们可以在类中的任何地方到达它,这意味着我们不必一直创建相同的对象实例。

但是让我们说我们正在谈论Asp.NET,一旦用户按下提交按钮,就会将数据发送到服务器并执行事件,并通过上述方法将发布的数据存储在数据库中,这样很可能是同一个用户如果我在页面执行后正确地知道了,终结器就会从内存(从堆中)中清除,这意味着我们也会从内存中丢失实例变量并在另一个post之后丢失DataContext应该再次为新页面循环创建。

因此,向全class公开宣布它的唯一好处就是上面的第一个文字。

或者还有其他什么吗?

提前致谢…

(如果我说错了,请修理我..)

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

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

首先,DataContext具有从数据库中提取的所有对象的内部缓存。 长时间使用DataContext将使其缓存无限增长,并在您拥有大型数据库时导致内存问题。 DataContext还支持在缓存中从缓存中返回对象,使您的对象快速失效。 由于这种陈旧性,任何对另一个DataContext或直接对数据库进行的更新和删除操作都会被忽视。

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

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

了解DataLayer类的设计非常重要。 在您的代码中,您只向我们展示了一种查询方法。 没有CUD方法。 是每个方法都是单个事务,还是要调用多个方法并在之后调用DataLayer上的SaveChanges? 如果需要最后一个选项,则需要将DataContext存储为实例字段,在这种情况下,您应该在DataLayer上实现IDisposable 。 当每个方法都是自己的事务时,您可以为每个方法创建一个DataContext,并且应该将一个DataContext包装在using语句中。 但请注意,从方法返回具有延迟加载属性的对象时,处理DataContext可能会导致问题。 处理DataContext时,无法再加载这些属性。 这里有更多有趣的信息。

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

对不起,我很抱歉:-)

您不希望在类级别上存储DataContext类 。 如果这样做,则必须在类上实现IDisposable接口 ,并在知道完成后调用Dispose方法。

最好在方法中创建一个新的DataContext,并在完成后使用using语句自动处理它。

即使DataContext上的IDisposable的实现什么都不做,这是一个实现细节,而暴露IDisposable接口是一个你应该始终遵守的契约

如果升级到LINQ-to-Entities并使用ObjectContext类 ,在完成它时必须在实例上调用Dispose,则会特别方便,否则,资源将泄漏直到下一次垃圾回收。

因此,向全class公开宣布它的唯一好处就是上面的第一个文字。

是的,声明类级变量是允许整个类访问同一个变量。 它不应该用于尝试故意防止垃圾收集发生。 属性,方法等上的访问修饰符用于确定类的外部或内部对象可以使用该段代码访问/修改/猴子。

在ASP.NET中,一旦请求被发送到浏览器,该页面请求的创建对象将在未来的某个时间点获得CGed,无论该变量是否是公共的。 如果希望信息保持在请求之间,则需要创建对象的单例实例,或者将对象序列化为会话或应用程序状态。

请参阅此示例 – “Linq to SQL DataContext Lifetime Management”: http : //www.west-wind.com/weblog/posts/246222.aspx此方法使生活更简单。