Linq-to-sql上下文数据库连接处理

7
什么规则决定了linq-to-sql数据上下文如何保持数据库连接的打开状态?
这个问题是在我们针对每个更新实体一个SubmitChanges()而不是整个批次的SubmitChanges()进行一些性能测试时出现的。结果如下:
插入3000个项目在一个SubmitChanges()调用中...持续时间:1318毫秒
插入3000个项目在一个SubmitChanges()调用中,在transactionscope内部...持续时间:1280毫秒
将3000个项目插入单独的SubmitChanges()调用...持续时间:4377毫秒
将3000个项目插入单独的SubmitChanges()调用中,使用事务...持续时间:2901毫秒
请注意,当为每个更改的实体执行单独的SubmitChanges()时,将所有内容放在事务内会提高性能,这对我们来说是非常意外的。在SQL服务器分析器中,我们可以看到在事务内部的单独的SubmitChanges()调用不会为每个调用重置DB连接,与没有事务的情况相反。
在什么情况下,数据上下文会保持连接处于打开状态?是否有关于linq-to-sql如何处理连接的详细文档可用?
4个回答

3
你没有展示完整的情况;LINQ-to-SQL默认会在调用SubmitChanges时包装一个事务。如果你将其与另一个事务一起使用,那么你就看不到连接重置;直到所有SubmitChanges调用完成并且外部事务提交后才能进行。

3

除了连接的打开/关闭时间,可能还有许多其他因素会影响时间。

编辑:在意识到linq2sql将缓存实体和脏实体分开管理后,我已经删除了关于跟踪实体的部分。

您可以使用Reflector或其他反汇编器检查SqlConnectionManager类上的方法来了解连接是如何在内部管理的。如果SubmitChanges在自己的事务中包装了提交,则会在提交后调用其IProvider(通常为SqlProvider,然后使用SqlConnectionManager)上的ClearConnection,但如果SubmitChanges是较大事务的一部分,则不会这样做。连接何时打开和关闭取决于是否有其他活动利用了SqlConnectionManager。


DataContext确实会跟踪更改的对象,但在默认生成的代码中(在这种情况下是由dbml设计器生成的),它使用INotifyPropertyChanging和INotifyPropertyChanged。有了这些实现,就不需要循环遍历所有对象了。无论如何,您是正确的,跟踪的实体数量会变得很大。 - Anders Abel

0

0

我最近也在这方面摸索。调用SubmitChanges 3000次不是一个好主意,但是根据每个记录被插入的重要性程度而定,您可能希望这样做,毕竟只需要1000ms。

事务范围和多个SubmitChanges是我期望看到的。由于您仍然在一个事务中,我期望看到SQL服务器处理得更好,它似乎确实如此。一个SubmitChanges和使用显式/隐式TransactionScope似乎会产生相同的结果,这是可以预料的。在那里不应该有任何/很大的性能差异。

我认为连接是在需要时创建的,但您必须记住,这将在提供程序中进行汇集,因此除非您的连接字符串正在更改,否则您应该钩住相同的连接池,这将产生相同的性能,无论采用哪种方法。由于LINQ-SQL在幕后使用SqlConnection,因此有关它的一些信息如下:

http://msdn.microsoft.com/en-us/library/8xx3tyca(VS.80).aspx

如果你想要获得暴力的性能,可以考虑使用带有显式 TransactionScope 的存储过程进行插入。如果这还不够快,可以考虑使用 SqlBulkCopy。3000行应该比1000毫秒更快地插入。

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