gpt4 book ai didi

c# - 林克 : Delete and Insert same Primary Key values within TransactionScope

转载 作者:可可西里 更新时间:2023-11-01 07:48:28 25 4
gpt4 key购买 nike

我想在一个事务中用新记录替换数据库中的现有记录。使用 TransactionScope,我有

using ( var scope = new TransactionScope())
{
db.Tasks.DeleteAllOnSubmit(oldTasks);
db.Tasks.SubmitChanges();

db.Tasks.InsertAllOnSubmit(newTasks);
db.Tasks.SubmitChanges();

scope.Complete();
}

我的程序抛出

System.InvalidOperationException: Cannot add an entity that already exists.

经过反复试验,我发现罪魁祸首在于删除和插入之间没有任何其他执行指令。如果我在第一个 SubmitChanges() 和 InsertAllOnSubmit() 之间插入其他代码,一切正常。谁能解释为什么会这样?这非常令人担忧。

我尝试了另一个更新对象:

IEnumerable<Task> tasks = ( ... some long query that involves multi tables )
.AsEnumerable()
.Select( i =>
{
i.Task.Duration += i.LastLegDuration;
return i.Task;
}
db.SubmitChanges();

这也不起作用。 db 没有获取对 Tasks 的任何更改。

编辑:

这种行为似乎与交易无关。最后,我采用了非常低效的更新:

newTasks.ForEach( t =>
{
Task attached = db.Tasks.Single( i => ... use primary id to look up ... );
attached.Duration = ...;
... more updates, Property by Property ...
}
db.SubmitChanges();

最佳答案

您可以尝试通过选择要更新的 ID 列表并检查列表是否包含每一项来一次更新多行,而不是插入和删除或进行多个查询。

此外,请确保将事务标记为已完成,以向事务管理器表明所有资源的状态是一致的,并且可以提交事务。

Dictionary<int,int> taskIdsWithDuration = getIdsOfTasksToUpdate(); //fetch a dictionary keyed on id's from your long query and values storing the corresponding *LastLegDuration*
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
var tasksToUpdate = db.Tasks.Where(x => taskIdsWithDuration.Keys.Contains(x.id));
foreach (var task in tasksToUpdate)
{
task.duration1 += taskIdsWithDuration[task.id];
}

db.SaveChanges();
scope.Complete();
}

根据您的情况,如果您的表非常大并且要更新的项目数量相当少,您可以反转搜索以利用索引。如果是这种情况,您现有的更新查询应该可以正常工作,所以我怀疑您是否需要反转它。

关于c# - 林克 : Delete and Insert same Primary Key values within TransactionScope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7431364/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com