Linq中的ChangeConflictException转换为Sql非并发更新

时间:2022-09-24 18:00:18

I'm using LINQ to SQL, and having a bit of an issue incrementing a view counter cross-connection.

我正在使用LINQ to SQL,并且在增加视图计数器交叉连接时遇到了一些问题。

The teeny bit of code I'm using is:

我正在使用的一小部分代码是:

t = this.AppManager.ForumManager.GetThread(id);
t.Views = t.Views + 1;
this.AppManager.DB.SubmitChanges();

Now in my tests, I am running this multiple times, non-concurrently. There are a total of 4 copies of the object performing this test.

现在在我的测试中,我多次运行,非同时运行。执行此测试的对象总共有4个副本。

That is to say, there is no locking issue, or anything like that but there are 4 data contexts.

也就是说,没有锁定问题,或类似的东西,但有4个数据上下文。

Now, I would expect this to work like this: fetch a row, modify a field, update the row. However, this is throwing a ChangeConflictException.

现在,我希望这样工作:获取一行,修改字段,更新行。但是,这会抛出ChangeConflictException。

Why would the change be conflicted if none of the copies of this are running concurrently?

如果没有任何副本同时运行,为什么更改会发生冲突?

Is there a way to ignore change conflicts on a certain table?

有没有办法忽略某个表上的更改冲突?

EDIT: Found the answer:

编辑:找到答案:

You can set "UpdateCheck = Never" on all columns on a table to create a last-in-wins style of update. This is what the application was using before I ported it to LINQ, so that is what I will use for now.

您可以在表的所有列上设置“UpdateCheck = Never”以创建最后一次更新的更新样式。这是应用程序在将其移植到LINQ之前使用的内容,所以这就是我现在要使用的内容。

EDIT2: While my fix above did indeed prevent the exception from being thrown, it did not fix the underlying issue:

编辑2:虽然我上面的修复确实阻止了抛出异常,但它没有修复底层问题:

Since I have more than one data context, there ends up being more than one cached copy of each object. Should I be recreating my data context with every page load?

由于我有多个数据上下文,因此最终会有多个每个对象的缓存副本。我是否应该在每次加载页面时重新创建数据上下文?

I would rather instruct the data context to forget everything. Is this possible?

我宁愿指示数据上下文忘记一切。这可能吗?

1 个解决方案

#1


I believe DataContext is indented to be relatively lightweight and short-lived. IMO, you should not cache data loaded with a DataContext longer than necessary. When it's short lived, it remains relatively small because (as I understand it) the DataContext's memory usage is primarily associated with tracking the changes you make to objects managed by it (retrieved by it).

我相信DataContext缩进为相对轻量级和短暂的。 IMO,您不应该缓存加载DataContext的数据超过必要的时间。当它很短暂时,它仍然相对较小,因为(据我所知),DataContext的内存使用主要与跟踪您对其管理的对象所做的更改(由它检索)相关联。

In the application I work on, we create the context, display data on the UI, wait for user updates and then update the data. However, that is necessary mainly because we want the update to be based on what the user is looking at (otherwise we could retrieve the data and update all at once when the user hits update). If your updates are relatively free-standing, I think it would be sensible to retrieve the row immediately before updating it.

在我工作的应用程序中,我们创建上下文,在UI上显示数据,等待用户更新,然后更新数据。但是,这是必要的,主要是因为我们希望更新基于用户正在查看的内容(否则我们可以检索数据并在用户点击更新时立即更新)。如果您的更新是相对独立的,我认为在更新之前立即检索该行是明智的。

You can also use System.Data.Linq.DataContext.Refresh() to re-sync already-retrieved data with data in the database to help with this problem.

您还可以使用System.Data.Linq.DataContext.Refresh()将已检索的数据与数据库中的数据重新同步,以帮助解决此问题。

To respond to your last comment about making the context forget everything, I don't think there's a way to do that, but I suspect that's because all there is to a context is the tracked changes (and the connection), and it's just as well that you create a new context (remember to dispose of the old one) because really you want to throw away everything that the context is.

为了回应你关于让上下文忘记一切的最后评论,我认为没有办法做到这一点,但我怀疑这是因为所有上下文都是被跟踪的变化(和连接),它就像好吧,你创建一个新的上下文(记得处理旧的上下文),因为你真的要扔掉上下文的一切。

#1


I believe DataContext is indented to be relatively lightweight and short-lived. IMO, you should not cache data loaded with a DataContext longer than necessary. When it's short lived, it remains relatively small because (as I understand it) the DataContext's memory usage is primarily associated with tracking the changes you make to objects managed by it (retrieved by it).

我相信DataContext缩进为相对轻量级和短暂的。 IMO,您不应该缓存加载DataContext的数据超过必要的时间。当它很短暂时,它仍然相对较小,因为(据我所知),DataContext的内存使用主要与跟踪您对其管理的对象所做的更改(由它检索)相关联。

In the application I work on, we create the context, display data on the UI, wait for user updates and then update the data. However, that is necessary mainly because we want the update to be based on what the user is looking at (otherwise we could retrieve the data and update all at once when the user hits update). If your updates are relatively free-standing, I think it would be sensible to retrieve the row immediately before updating it.

在我工作的应用程序中,我们创建上下文,在UI上显示数据,等待用户更新,然后更新数据。但是,这是必要的,主要是因为我们希望更新基于用户正在查看的内容(否则我们可以检索数据并在用户点击更新时立即更新)。如果您的更新是相对独立的,我认为在更新之前立即检索该行是明智的。

You can also use System.Data.Linq.DataContext.Refresh() to re-sync already-retrieved data with data in the database to help with this problem.

您还可以使用System.Data.Linq.DataContext.Refresh()将已检索的数据与数据库中的数据重新同步,以帮助解决此问题。

To respond to your last comment about making the context forget everything, I don't think there's a way to do that, but I suspect that's because all there is to a context is the tracked changes (and the connection), and it's just as well that you create a new context (remember to dispose of the old one) because really you want to throw away everything that the context is.

为了回应你关于让上下文忘记一切的最后评论,我认为没有办法做到这一点,但我怀疑这是因为所有上下文都是被跟踪的变化(和连接),它就像好吧,你创建一个新的上下文(记得处理旧的上下文),因为你真的要扔掉上下文的一切。