在多个方法调用之间共享同一个DataServiceContext好还是不好?

3
我想知道DataServiceContext实例的标准使用方法。如果我的类有多个需要在上下文中执行操作的方法,那么我应该在每个方法内创建新的上下文实例,还是将上下文作为类的单一成员被所有方法共享?
我之所以问这个问题,是因为我最近看到另一个开发人员在我正在处理的某些代码中发表的评论,提到需要在添加一些对象后重新创建上下文,然后再执行一些其他操作。
也就是说,我应该这样做:
public class ServiceHelper
{
  public void DoSomething()
  {
    DataContext ctx = new DataContext(Uri);

    //do something with the context and call SaveChanges()
  }

  public int GetSometing()
  {
    DataContext ctx = new DataContext(Uri);

    return ctx.GetSomething();
   }
}

或者是这样:
public class ServiceHelper
{
  private readonly DataContext _ctx = new DataContext(Uri);

  public void DoSomething()
  {
    //do something with _ctx and call SaveChanges()
  }

  public int GetSomething()
  {
    return _ctx.GetSomething();
  }
}

我还应该补充一点,这是在ASP.NET MVC应用程序的上下文中,所以这里的ServiceHelper类将在每个页面请求时重新构建。

编辑

好吧,据微软公司称,两种方法都是有效的,因为它们是短暂的类,但我仍然想知道它们是否同样“安全”和等效。也就是说,如果我添加/更新了一些实体并调用SaveChanges,那么可能有一个单独的应用程序对相同实体进行了更新,然后我再次使用相同的上下文实例检索这些实体,那么是否会像我在第二个操作之前创建新的上下文时那样表现一样?

结论 

我刚发现这个,我认为它有助于解释区别:

默认情况下,客户端仅将响应源中的条目实体化为对象,以便那些尚未由DataServiceContext跟踪的实体。 这意味着不会覆盖已经在高速缓存中的对象。此行为由为查询和加载操作指定MergeOption值来控制。 此选项是通过在DataServiceContext上设置MergeOption属性来指定的。 默认合并选项值为AppendOnly。这仅实例化尚未被跟踪的实体对象,这意味着现有对象不会被覆盖。 防止从数据服务更新对客户端上的对象进行更改的另一种方法是指定PreserveChanges。 当您指定OverwriteChanges时,客户端上对象的值将由响应源中的条目的最新值替换,即使已对这些对象进行了更改也是如此。

因此,如果我更新了一些实体,然后有一个单独的应用程序进行了进一步的更改,然后我再次使用相同的DataServiceContext实例检索这些实体,那么取决于MergeOption设置是什么,我将获取实体以数据库中的状态还是以本地最后一次拥有它们的状态。


这个类看起来像是一个过度设计的全局变量。这样做真的是一个好主意吗?应该有更好的传递数据的方式。 - robbmj
1个回答

3

Msdn 指出

一般来说,DataContext实例被设计为在一个"工作单元"中使用,无论你的应用程序如何定义。DataContext是轻量级的,并且创建成本不高。典型的LINQ to SQL应用程序在方法范围内或作为表示相关数据库操作逻辑集合的短期类的成员创建DataContext实例。

当然,前提是您使用LINQ to SQL。但即使在其他技术/库中,上下文通常也是非常轻量级的对象。在大多数情况下,物理连接不会断开(但逻辑连接会)。我猜您关心的问题与连接池有关,因此只要使用一个连接池(应该这样做),就可以遵循Msdn的建议。因此,

public void DoSomething()
{
    using(DataContext ctx = new DataContext(Uri))
    {
         //do something with the context and call SaveChanges()
    }
}

我想任何一种方法都是有效的,因为我认为这些类是“短暂的”。在每个方法中重新创建似乎更安全,但类成员更清晰/代码更少。 - mclaassen
这真的取决于你的应用程序。想法是*context很轻量级,只是不要让它长时间挂起。 - oleksii
我真的很想知道,为什么我不能一直保留它?当从一个新实例化的上下文中添加/更新/检索实体时,与我已经用于执行其他操作的上下文相比,有什么不同的行为(忽略性能差异)? - mclaassen
1
此外:拥有 DataContext 实例的类不管理其生命周期。有人可能构建一个桌面应用程序版本,使用此数据上下文管理器,而不遵循无状态应用程序设计的规范。 - Aidanapword
因为上下文与工作单元相关联,它更或多或少是一个事务。您不会让事务长时间保持打开状态,对吗?在上下文中,这意味着将所有更改保存在内存中,因为您可能想要还原某些内容(按设计)。如果您让它长时间打开,您将占用不需要的内存,因此您将有较少的内存来处理其他请求。至少这是我的理解。 - oleksii

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接