具有日期时间字段的实体框架并发性



我在更新模型的实体时遇到问题:

var intervenant = this.IntervenantRepository.GetAll().FirstOrDefault(intervenant => intervenant.Id == intervenantId);
if (IsInscrire)
{
intervenant.MotifdesinscId = null;
intervenant.IsInscrit = true;
}
this.IntervenantRepository.Update(intervenant);

我在干预实体模型中处理与属性LastModificationTime的一致性

[ConcurrencyCheck] 
public DateTime LastModificationTime { get; set; }

当我用上面的源代码更新我的实体时,我得到了一个DbUpdateConcurrencyException,我认为问题是我在属性LastModificationTime中得到的数据是2020-03-09T10:02:37,但在数据库中,该列包含数据2020-03-09 10:02:37.4570000。

有没有任何解决方案可以让我处理这个问题,因为我在其他实体中也得到了它?

我的建议是完全忽略LastModificationTime属性并使用TimestampAttribute。这实际上就是@marc_s在评论中所暗示的。

public class Intervenant
{
// Your properties here
[Timestamp]
public byte[] RowVersion { get; set; }
}

代码中的TimeStamp dataannotations属性优先。

它使用一个表示时间戳的字节数组,以避免出现这样的问题。

它在实体类中只能应用于字节数组类型属性一次它在SQL Server数据库中创建一个时间戳数据类型为的列。实体框架API在数据库中的UPDATE语句的并发检查中自动使用此时间戳列。

如果您不想使用多个值并让框架自己处理,请使用此。它将稍微扩展一下表,但它将解决任何此类问题。

ConcurrencyCheckAttribute

解决方案是修改我的实体配置,并删除此行:

.HasColumnType("datetime")

有了这个配置,我就不再有问题了:

builder.Property(e => e.LastModificationTime)
.HasColumnName("INTERVENANT_MODIFQUAND");

我在尝试使用EF和DateTime字段作为并发检查字段时遇到了同样的挑战。EF并发代码似乎不遵守来自元数据(edmx(的精度设置,即Type=";DateTime";精度=";3〃;。数据库日期时间字段将在字段中存储一个毫秒组件(即2020-10-18 15:49:02.123(。即使将实体的原始值设置为包含毫秒组件的日期时间,SQL EF也会生成以下内容:

UPDATE [dbo].[People]
SET [dateUpdated] = @0
WHERE (([PeopleID] = @1) AND ([dateUpdated] = @2))
-- @0: '10/19/2020 1:07:00 AM' (Type = DateTime2)
-- @1: '3182' (Type = Int32)
-- @2: '10/19/2020 1:06:10 AM' (Type = DateTime2)

正如您所看到的,@2是一个没有毫秒成分的字符串表示。这将导致您的更新失败。

因此,如果要使用DateTime字段作为并发键,则在检索记录时必须从数据库字段中剥离毫秒/Ticks,并且只使用类似的剥离DateTime传递/更新字段。

//strip milliseconds due to EF concurrency handling
PeopleModel p = db.people.Where(x => x.PeopleID = id);
if (p.dateUpdated.Millisecond > 0)
{
DateTime d = new DateTime(p.dateUpdated.Ticks / 10000000 * 10000000);
object[] b = {p.PeopleID, d};
int upd = db.Database.ExecuteSqlCommand("Update People set dateUpdated=@p1 where peopleId=@p0", b);
if (upd == 1)
p.dateUpdated = d;
else
return InternalServerError(new Exception("Unable to update dateUpdated"));
}
return Ok(p);

当用新值更新字段时,也去掉的毫秒数

(param)int id, PeopleModel person;
People tbl = db.People.Where(x => x.PeopleID == id).FirstOrDefault();
db.Entry(tbl).OriginalValues["dateUpdated"] = person.dateUpdated;
//strip milliseconds from dateUpdated since EF doesn't preserve them
tbl.dateUpdated = new DateTime(DateTime.Now.Ticks / 10000000 * 10000000);

最新更新