避免跨线程/流程数据库评估的最佳实践

时间:2012-10-15 14:05:37

标签: c# sql-server design-patterns linq-to-sql multithreading

我正在开发MVC Web应用程序。

这意味着我正在创建视图,模型,视图模型。我使用linq-to-sql作为数据库提供程序,我实现了自定义Unit-of-Work模式,以及数据源,存储库和服务模式,它们看起来完美(在我的实现中)并且与直接{{1完全分离代码。实际上,从任何专为单元测试设计的数据库,我都可以使用内存数据源测试我的应用程序,而不会影响数据库。

最终我遇到了一个问题:我没有再次保护跨线程(或跨进程,因为据我所知,IIS可以使用单个Web应用创建多个应用域)操作

例如,我有一张包含一些记录的表格。并且每次都会发生一个Web请求(在控制器内部,然后是服务,然后是存储库),在最大的假设SQL列上选择SQL表'行,然后在该表中插入另一行{{1 }}

如果两个或多个线程或进程执行相同的操作,则重复的值可以出现在数据库中。前段时间,当我的webapp变得更小时,我在SELECT语句中使用了直接的SQL代码和简单的TicketIdTransactionScope using块内部锁定了记录I'修改(或其他任何)阻止所有其他数据库客户端等到我完成。

有了这些模式,我忘了一件事:
如何实际实施数据库多路访问保护问题
没有任何直接的SQL代码。

2 个答案:

答案 0 :(得分:4)

  

如何实际实现数据库多路访问保护问题?

这是数据库引擎的工作。如果报告任何问题,确保您的应用程序正常失败是您的工作。请参阅Locking in the Database Engine

  

例如,我有一张包含一些记录的表格。并且每次都会出现一个Web请求   (在控制器内,然后是服务,然后是存储库)在最大值>上选择SQL表'行让我们说TicketId列,然后在该表中插入另一行(该列值+ 1)。

我在这里得到的印象是,考虑到你试图复制它的行为,你似乎对你的数据库没有多少信心。将您的字段设置为auto-increment,这应该可以解决您的问题。如果你来实现你自己的手动自动增量,那么你需要使用某种形式的锁定,因为你基本上拥有的是竞争条件,例如。

private static object lockObject = new Object();

lock(lockObject)
{
    ... DB stuff
}

对于跨进程锁定,您需要查看可能已命名的Mutex

答案 1 :(得分:1)

为什么不使用单个表来表示票号和使用Seriliazable transaction isolation level的交易?

int GetTicketNumber(bool shouldIncrement)
{

   if(shouldIncrement)
   {
     // use transaction with serilizable isolation level
     select and update
   }
   else
   {
     //just select
   }

}