LINQ中的数据冲突

时间:2020-03-05 18:44:29  来源:igfitidea点击:

使用SubmitChanges()进行更改时,LINQ有时会死于带有错误消息"未找到或者更改行"的" ChangeConflictException"异常,而没有任何迹象表明存在冲突的行或者具有更改的字段当另一个用户更改了该行中的某些数据时发生冲突。

是否有任何方法可以确定哪一行发生冲突以及它们发生在哪些字段中,还有没有办法使LINQ忽略该问题并简单地提交数据呢?

另外,有人知道行中的任何数据已更改时,还是仅当LINQ试图更改的字段中的数据已更改时,才会发生此异常吗?

解决方案

回答

在与错误消息所描述的内容完全无关的情况下,我遇到了此错误。

我所做的是通过一个DataContext加载LINQ对象,然后尝试通过不同的DataContext为该对象提交SubmitChanges()给出了完全相同的错误。

我要做的是先调用DataContext.Table.Attach(myOldObject),然后再调用SubmitChanges(),就像一个魅力一样。

值得一看,尤其是在我们认为根本不应该存在任何冲突的情况下。

回答

这是一种查看冲突在哪里的方法(这是一个MSDN示例,因此我们需要大量自定义):

try
{
    db.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException e)
{
    Console.WriteLine("Optimistic concurrency error.");
    Console.WriteLine(e.Message);
    Console.ReadLine();
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
        MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType());
        Customer entityInConflict = (Customer)occ.Object;
        Console.WriteLine("Table name: {0}", metatable.TableName);
        Console.Write("Customer ID: ");
        Console.WriteLine(entityInConflict.CustomerID);
        foreach (MemberChangeConflict mcc in occ.MemberConflicts)
        {
            object currVal = mcc.CurrentValue;
            object origVal = mcc.OriginalValue;
            object databaseVal = mcc.DatabaseValue;
            MemberInfo mi = mcc.Member;
            Console.WriteLine("Member: {0}", mi.Name);
            Console.WriteLine("current value: {0}", currVal);
            Console.WriteLine("original value: {0}", origVal);
            Console.WriteLine("database value: {0}", databaseVal);
        }
    }
}

要使其忽略该问题并继续提交:

db.SubmitChanges(ConflictMode.ContinueOnConflict);

回答

这些(可以将部分类添加到数据上下文中来了解其工作原理:

public void SubmitKeepChanges()
{
    try
    {
        this.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
    catch (ChangeConflictException e)
    {
        foreach (ObjectChangeConflict occ in this.ChangeConflicts)
        {
            //Keep current values that have changed, 
//updates other values with database values

            occ.Resolve(RefreshMode.KeepChanges);
        }
    }
}

public void SubmitOverwrite()
{
    try
    {
        this.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
    catch (ChangeConflictException e)
    {
        foreach (ObjectChangeConflict occ in this.ChangeConflicts)
        {
            // All database values overwrite current values with 
//values from database

            occ.Resolve(RefreshMode.OverwriteCurrentValues);
        }
    }
}

public void SubmitKeepCurrent()
{
    try
    {
        this.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
    catch (ChangeConflictException e)
    {
        foreach (ObjectChangeConflict occ in this.ChangeConflicts)
        {
            //Swap the original values with the values retrieved from the database. No current value is modified
            occ.Resolve(RefreshMode.KeepCurrentValues);
        }
    }
}

回答

"而且还有一种方法使LINQ忽略该问题,而只是提交数据而已吗?"

我们可以将实体上的"更新检查"属性设置为"从不",以停止将该字段用于乐观并发检查。

我们还可以使用:

db.SubmitChanges(ConflictMode.ContinueOnConflict)

回答

当O / R-Designer中的列或者类型与SQL数据库中的列不匹配时,有时也会出现错误"未找到或者更改行",尤其是当一列在SQL中可为空但在O / R中不可为空时R-Designer。

因此,请检查O / R-Designer中的表映射是否与SQL数据库匹配!

回答

那些方法不完整吗?我们是否不想重试提交或者将其包装在某种循环中,否则无法保证在发生冲突时提交更改?