更高效的数据库访问
我是数据库和linq的新手,所以我的问题可能被认为是微不足道的。 我目前在每个类中启动所有数据库请求:
DataClassesDataContext db = new DataClassesDataContext()
然后我继续在方法中做出我需要的任何linq请求,并继续使用主应用程序逻辑。
现在,两个有趣的查询:
1)我相信我已经看到人们在’使用’中包含数据库使用。 如:
using (DataClassesDataContext db = new DataClassesDataContext()) { ... }
如果这是正确的,那么这不是说我的类不能再使用成员’db’变量了,而是需要在每个函数调用中进行那些db请求吗? 另外,如果我不在通话中使用’使用’,究竟会发生什么?
2)在启用SQL事件探查器的情况下运行我的应用程序,我看到许多连接打开和关闭。 这是否意味着每个DataClassesDataContext调用都会建立一个单独的连接? 它看起来效率低下,在实际使用的每个类中实际使DataClassesDataContext对象成为静态的正确方法是什么?
通常,每个数据库对话应使用一个DataContext
。 只有您可以准确地确定对话是什么,但通常它是一个完整的请求(例如,获取用户的愿望清单,或者获取用户的已关闭订单),您可能会将其视为“工作单元”。
通常情况是这样的:
WishList wishlist; using(var context = new DataContext(connectionString)) { var service = new UserWishListService(context); wishlist = service.GetUserWishList(); }
另外,如果我不在通话中使用,究竟会发生什么?
DataContext
将不会被正确处理(除非你已经包装在try-catch-finally
,但通常你应该使用using
)。
这是否意味着每个
DataClassesDataContext
调用都会建立一个单独的连接?
不完全的。 您的应用程序将受益于SQL Server ADO.NET提供程序的内置连接池 。 不要担心这一点,让供应商为您管理。
它看起来效率低下,在实际使用的每个类中实际使
DataClassesDataContext
对象成为static
的正确方法是什么?
绝对不。 DataContext
不是线程安全的(事实上,它们是线程不安全的)并且它在其上面写着“有龙”。 此外,即使是单线程上下文, static DataContext
也是一个糟糕的选择,因为DataContext
维护了从数据库中提取的所有实体的缓存(用于对象跟踪)。 随着时间的推移,内存消耗将变得巨大。
由于您添加了asp.net标记,这意味着您正在使用HTTP调用中的上下文。 静态成员上下文在asp.net中不可用,因为您需要同步对它的访问,并且由于每次调用都需要您的数据上下文,因此您一次只能提供一个HTTP响应,这是一个史无前例的可扩展性惨败。
这就是为什么数据上下文是“在旅途中”创建和处理的原因。 事实上, 类规范明确地提出了这种使用模式:
通常,DataContext实例设计为持续一个“工作单元”,但是您的应用程序定义该术语。 DataContext是轻量级的,创建起来并不昂贵。 典型的LINQ to SQL应用程序在方法范围内创建DataContext实例,或者作为表示相关数据库操作的逻辑集的短期类的成员。
对于ASP.Net来说,一个明智的“工作单元”上下文就是HTTP调用本身。 有关此主题的更长时间的讨论可以在Linq to SQL DataContext Lifetime Management中找到 。
连接打开/关闭的问题不是问题。 通常情况下,连接是汇集的,“开放”只不过是重用池中的连接。 如果您正在打开重量级(完全成熟的登录),那么您正在使用错误的池。 比较登录/秒和连接重置/秒计数器将很快显示是否确实如此。