简体   繁体   English

在 EF 6 中设置值和处理并发

[英]Setting values and handling concurrency in EF 6

I am using EF 6.1 and my service update method looks like so我正在使用 EF 6.1,我的服务更新方法如下所示

public async override Task<int> UpdateAsync(Module updated)
{
    var entity = await _context.Modules
        .Where(e => e.Id == updated.Id)
        .FirstOrDefaultAsync();

    // update existing values
    _context.Entry(entity).CurrentValues.SetValues(updated);

    // do not update
    _context.SetModified(entity, "AddOnlyProperty", false);

    return await base.UpdateAsync(entity);
}

My base UpdateAsync looks like so我的基本 UpdateAsync 看起来像这样

public async virtual Task<int> UpdateAsync(T updated)
{
    var results = await ValidateAsync(updated);

    if (!results.IsValid)
    {
        throw new ValidationException(results.Errors);
    }

    if (_context.GetState(updated) == EntityState.Detached)
    {
        _context.Set<T>().Attach(updated);
        _context.SetState(updated, EntityState.Modified);
    }

    // we do not want the createdDate to change when an update is being done
    _context.SetModified(updated, "CreatedDate", false);
    _context.SetModified(updated, "CreatedByUserId", false);

    return await _context.SaveChangesAsync();
}

This method is very simple, it copies the changes from updated into the entity, that way EF will only apply the changes needed when it creates the SQL.这种方法非常简单,它将更新中的更改复制到实体中,这样 EF 只会在创建 SQL 时应用所需的更改。

My problem is that concurrency doesnt seem to be working, i would expect a DbConcurrencyException to be thrown?我的问题是并发似乎不起作用,我希望抛出 DbConcurrencyException 吗?

Here is my basic Module object这是我的基本模块对象

public class Module : EntityBase, IEntityVersion, IEntityDelete
{
    public long Id { get; set; }

    public string Name { get; set; }

    public byte[] RowVersion { get; set; }
}

I have configured RowVersion as a rowVersion field in my Module.config file, like so我在 Module.config 文件中将 RowVersion 配置为 rowVersion 字段,如下所示

this.Property(e => e.RowVersion)
    .IsRowVersion();

Now when i perform an update with an old rowVersion value, the update seems to still take place?现在,当我使用旧的 rowVersion 值执行更新时,更新似乎仍在发生? Have i missed a configuration setting or am i doing this wrong?我错过了配置设置还是我做错了?

Should an exception be thrown, or should i be checking if the rowVersion values match myself?应该抛出异常,还是应该检查 rowVersion 值是否与我自己匹配?

You retrieve the record.您检索记录。

You then modify the record.然后修改记录。

Someone else modifies the record too, and saves the change.其他人也修改了记录,并保存了更改。

You retrieve the record again, and update the values to match your desired values.您再次检索记录,并更新值以匹配所需的值。

You save your changes.您保存更改。

The problem here is the "You retrieve the record again" step.这里的问题是“您再次检索记录”步骤。 Because you do this after the other person saved the changes, you get the new row version value already.因为您在其他人保存更改执行此操作,所以您已经获得了新的行版本值。 This is the step you need to skip.这是您需要跳过的步骤。

One way of handling it is using one Context throughout the process, and leaving the entity-to-be-modified attached to the context.处理它的一种方法是在整个过程中使用一个Context ,并将要修改的实体附加到上下文。 Entity Framework will be able to keep track of the original values.实体框架将能够跟踪原始值。

Another way of handling it is keeping track of the original values yourself.另一种处理它的方法是自己跟踪原始值。 When you want to save the changes, create a detached entity, set the properties to the original values, attach it to the context, and then set the properties to the modified values.当您想要保存更改时,创建一个分离的实体,将属性设置为原始值,将其附加到上下文,然后将属性设置为修改后的值。


Actually, thinking about it some more, instead of using on EF's concurrency handling, you should be able to trivially code your own here:实际上,再考虑一下,而不是使用 EF 的并发处理,您应该能够在这里轻松编写自己的代码:

var entity = await _context.Modules
    .Where(e => e.Id == updated.Id)
    .FirstOrDefaultAsync();
if (entity == null) {
  ... // throw exception about record not existing in the database
}
if (BitConverter.ToInt64(entity.RowVersion, 0) != BitConverter.ToInt64(updated.RowVersion, 0)) {
  ... // throw exception about record having been updated in the database
}
... // your existing code to update the entity can go here

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM