更高效的数据库访问

3

我对数据库和linq都很陌生,所以我的问题可能被认为是微不足道的。我目前在每个类中都使用以下代码开始所有的数据库请求:

 DataClassesDataContext db = new DataClassesDataContext()

然后我开始在方法内进行任何需要的linq请求,并继续主要应用逻辑。

现在,有两个有趣的查询:

1)我相信我已经看到过人们在“using”中包装数据库使用。例如:

using (DataClassesDataContext db = new DataClassesDataContext())
{
    ...
}

如果这是正确的,那么我的类就不能再使用成员变量'db'了,而是需要在每个函数调用中进行db请求。此外,如果我不在调用中使用'using',会发生什么呢?
2) 启用SQL Profiler运行我的应用程序后,我看到有很多连接在打开和关闭。这是否意味着每个DataClassesDataContext调用都会创建一个单独的连接?这似乎效率低下,所以实际上正确的方法是将DataClassesDataContext对象作为每个被使用的类中的静态对象吗?

还有其他框架,比如Developer Express XPO,支持Linq类型的查询。 - abmv
2个回答

1
一般来说,每个数据库对话应该使用一个 DataContext 。只有你可以确定什么是一次对话,但通常它是一个完整的请求(例如获取用户的愿望清单或获取用户的已关闭订单),你可以把它看作是一个“工作单位”。
通常情况下会发生以下情况:
WishList wishlist;
using(var context = new DataContext(connectionString)) {
    var service = new UserWishListService(context);
    wishlist = service.GetUserWishList();
}

此外,如果我在调用中不使用using,会发生什么? DataContext将无法正确释放(除非您已经包装在try-catch-finally中,但通常应该只使用using)。
这是否意味着每个DataClassesDataContext调用都会建立一个单独的连接?
不完全是。您的应用程序将受益于SQL Server ADO.NET提供程序内置的连接池。不要担心这个问题,让提供程序为您管理它。
看起来效率低下,那么真正正确的方法是将DataClassesDataContext对象作为每个正在使用的类中的static吗?
绝对不行。 DataContext 不是线程安全的(事实上,它们是线程不安全的),这会带来很多问题。此外,即使是单线程环境下,static DataContext 也是一个糟糕的选择,因为 DataContext 维护了一个缓存(用于对象跟踪),其中包含从数据库中检索的所有实体。随着时间的推移,内存消耗将变得巨大。

1

既然你添加了 asp.net 标签,那就意味着你正在一个 HTTP 调用内使用上下文。在 asp.net 中无法使用静态成员上下文,因为你需要同步访问它,而且由于每个调用都需要使用你的数据上下文,所以一次只能服务于一个 HTTP 响应,这是一个规模极大的可扩展性灾难。

这就是为什么数据上下文会被“即时创建和处理”的原因。实际上,类规范 明确指出了这种使用模式:

通常情况下,DataContext 实例用于一个 “工作单元”,不过这个术语的定义取决于你的应用程序。DataContext 是轻量级的,并且创建成本不高。典型的 LINQ to SQL 应用程序在方法范围内或作为短寿命周期类的成员中创建 DataContext 实例,这些类代表了相关数据库操作的逻辑集合。

对于 ASP.Net,一个明智的“工作单元”上下文就是 HTTP 调用本身。关于此主题的更长讨论可以在 Linq to SQL DataContext Lifetime Management 中找到。

连接打开/关闭的问题并不是问题。通常连接被池化了,而“打开”只是从池中重新使用连接。如果你的打开是重量级的(完全成型的登录),那么你正在错误地使用池化。比较 Logins/secConnection Resets/sec 计数器将很快揭示是否确实是这种情况。

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