我在更新模型的实体时遇到问题:
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);