只用linq更新1列

时间:2009-07-23 14:38:20

标签: sql linq concurrency

我正在使用linq从数据库中的表中检索一行。 现在我只更新1列。 然后我将其更新回数据库。

这很顺利,除了其他进程/线程/用户更改任何其他字段的时间 在那种情况下,我得到一个异常(乐观并发),告诉我注意,自从我上次使用linq获取对象后,值已经改变。

由于我只对这一列感兴趣,我可以告诉linq只更新此列并忽略其他列吗? (并警告我这一栏确实已经改变了)

[R

9 个答案:

答案 0 :(得分:4)

您可以通过捕获ChangeConflictException

来检测并解决并发问题
using (var db = new MyDataContext())
{
    var row = db.MyTable.Single(x => x.Id == tableId);  // Getting the row

    row.Column = columnNewValue;  // Assign the new value

    try
    {
        db.SubmitChanges();
    }
    catch (ChangeConflictException)
    {
        db.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
        db.SubmitChanges();
    }
}

使用RefreshModeKeepChanges对客户端对象所做的所有更改都将保留,其他列上的其他用户/进程/线程的更改将合并。

在您的情况下,只会更改您的列。

推荐文章:

答案 1 :(得分:1)

我不太清楚这一点,但看起来你可以使用ColumnAttribute上的UpdateCheck.Never枚举值来完全避免并发检查。

MSDN

答案 2 :(得分:1)

MSDN中有一篇很好的文章:

Simultaneous Changes

以下示例(文章中的稍后一点)可能特别重要:

public partial class Northwind : DataContext
{
   ...

   public void UpdateProduct(Product original, Product current) {
      // Execute the stored procedure for UnitsInStock update
      if (original.UnitsInStock != current.UnitsInStock) {
         int rowCount = this.ExecuteCommand(
            "exec UpdateProductStock " +
            "@id={0}, @originalUnits={1}, @decrement={2}",
            original.ProductID,
            original.UnitsInStock,
            (original.UnitsInStock - current.UnitsInStock)
         );
         if (rowCount < 1)
            throw new Exception("Error updating");
      }
      ...
   }
}

您的存储过程是:

create proc UpdateProductStock
   @id               int,
   @originalUnits    int,
   @decrement         int
as
UPDATE Product 
SET originalUnits=@originalUnits,
    decrement=@decrement
WHERE id=@id

根据我的经验,最好的方法是制作自己的存储过程。 Linq不提供一种简单的方法来同时进行更改,除非您将(几乎)所有列的“UpdateCheck”属性设置为“Never”。

答案 3 :(得分:0)

听起来你可能正在以单例模式使用DataContext,或者至少在多个线程中共享它。

当您在DataContext上调用SubmitChanges时,将执行DataContext知道的所有数据库更改。

DataContext仅用作工作单元对象,并在您完成该工作后立即处理。

答案 4 :(得分:0)

我找到了 this 。那是你要找的吗?

如果这不能解决问题,您可以随时构建 sql update statement 并执行它。

答案 5 :(得分:0)

您可以执行此操作,但这需要您以某种方式构建代码。

例如,您有一个需要单独更新的说明和金额。然后,您将创建2个方法:

  • updateAmount,其中包含密钥和金额。
  • udateDesription,它包含关键和描述。

然后在例如更新的数量方法:

  • 创建可序列化的交易
  • 从数据库中读取行
  • 更新了内存中的金额
  • 将记录保存到数据库
  • 提交交易

当你这样做时,你只会改变你想要改变的东西。

我们使用此模式的时间是由于审核要求。您可以说此用户更改了金额,此用户更改了说明。并非每个用户都更改了记录,您需要查看数据以查看他们的操作。

答案 6 :(得分:0)

我读了一篇文章,讨论在运行时更改UpdateCheck属性的可能性。 (根据'我可能需要某一天'类别提交它,但到目前为止我还没需要它。)

http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2007/12/20/10038.aspx

答案 7 :(得分:0)

如果您有权更改数据库架构,请将时间戳列添加到相关数据表中,然后确保没有为并发更新设置其他列(它应自动获取TimeStamp列,但可能需要如果没有,则重新生成dbml中的表。当你有一个TimeStamp列时,LINQ to SQL只会在进行并发检查时使用该字段,从而允许更加离散的更新。

答案 8 :(得分:0)

使用http://plinqo.com处的PLINQO框架,如果您喜欢使用属于PLINQO的批处理操作,则可以更新一列。

context.Task.Update(t =&gt; t.Id == 1,t2 =&gt; new Task {StatusId = 2});

这将执行更新任务集StatusId = 2其中Id = 1