如何使用linq-to-sql同时增加页面查看次数?

Aus*_*tin 5 c# architecture asp.net-mvc concurrency linq-to-sql

我有一个使用Linq-to-SQL的ASP.NET MVC 3 Web应用程序用于我的数据访问层.我每次调用Details操作时都试图增加一个Views字段,但是如果两个人碰巧同时遇到了这个动作,我会在db.SubmitChanges()上收到"Row not found or changed"错误.

public ActionResult Details(int id)
{
    DataClassesDataContext db = new DataClassesDataContext();

    var idea = db.Ideas.Where(i => i.IdeaPK == id).Single();

    idea.Views++;

    db.SubmitChanges();

    return View(new IdeaViewModel(idea));
}
Run Code Online (Sandbox Code Playgroud)

我可以在我的.dbml(数据模型)中将Views字段的UpdateCheck设置为"Never",这样可以消除错误,但是想法记录可以使用相同的Views count更新两次.即

First instance of Details action gets idea record with Views count of 1.
Second instance of Details action gets idea record with Views count of 1.
First instance increments Views to 2
First instance commits
Second instance increments Views to 2
Second instance commits

Result: Views field is 2 
Expected Result: Views field should be 3
Run Code Online (Sandbox Code Playgroud)

我查看了使用TransactionScope,但是我从两个调用之一得到了以下死锁错误:

事务(进程ID 54)在锁资源上与另一个进程发生死锁,并被选为死锁牺牲品.重新运行该交易.

当我将我的动作更新为:

public ActionResult Details(int id)
{
    DataClassesDataContext db = new DataClassesDataContext();

    using (var transaction = new TransactionScope()){
        var idea = db.Ideas.Where(i => i.IdeaPK == id).Single();

        idea.Views++;

        db.SubmitChanges();

        return View(new IdeaViewModel(idea));
    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试使用TransactionScopeOptions增加的TransactionScope超时,并且似乎没有帮助(但我可能必须将其设置在其他地方也一样).我可以通过使用db.ExecuteQuery在单个SQL命令中增加来解决这个例子,但我试图弄清楚如何使这个工作,所以我会知道在更复杂的场景(我想要执行的地方)做什么单个事务中的多个命令).

Kir*_*oll 2

您不应该需要事务或存储过程。只需使用DataContext.ExecuteCommand

db.ExecuteCommand("UPDATE Ideas SET Views = Views + 1 WHERE IdeaPK = {0}", id);
Run Code Online (Sandbox Code Playgroud)

这会将其作为一个 SQL 语句执行,因此是原子的。