postgresql 在不同dbcontext的情况下使用实体框架时发生并发错误

pu82cl6c  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(101)

我有一个给定的实体'学生'与基于应用程序的并发控制定义在'LastModified'。

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; } = null!;
    public DateTimeOffset Created { get; set; }
    [ConcurrencyCheck]
    public DateTimeOffset LastModified { get; set; }
}

字符串
现在,我在仓库层编写了更新函数,如下所示:

public async Task<UpsertResponse> UpdateAsync(Entities.Student student)
{
    using var context = _dbContextFactory.CreateDbContext(readOnly: true); //Create reader DbContext instance
    var studentToBeModified = await context.Student.FirstOrDefaultAsync(x => x.Id == student.Id).ConfigureAwait(false);

    if (!studentToBeModified)
    {
        studentToBeModified.Name = student.Name;
        studentToBeModified.LastModified = DateTimeOffset.UtcNow;

        using var context = _dbContextFactory.CreateDbContext(readOnly: false); //Create writer DbContext instance
        context.Update(studentToBeModified);
        await context.SaveChangesAsync().ConfigureAwait(false); //Throws DbUpdateConcurrencyException
    }
}


上述问题可以通过以下2种方式解决,并具有一些优点/缺点:
1.使用一个writer DbContext示例,并将其用于读写操作。
缺点:这不是在读写数据库示例上分配负载的最佳方法,因为写示例只有1个,但读示例可以扩展到很多个
1.写SaveChangesAsync拦截器来更新LastModified值。
缺点:Overhead to have an interceptor
使用实体框架处理基于应用程序的并发检查而不影响应用程序性能的更好方法是什么?
如果还有其他选择,请分享

olmpazwi

olmpazwi1#

如果在修改studentToBeModified的属性之前,您使用Attach()在writer context中开始跟踪它,则SaveChangesAsync()将成功。
你的if的主体将变成:

using var context = _dbContextFactory.CreateDbContext(readOnly: false); 
context.Student.Attach(studentToBeModified);
studentToBeModified.Name = student.Name;
studentToBeModified.LastModified = DateTimeOffset.UtcNow;
await context.SaveChangesAsync().ConfigureAwait(false);

字符串

相关问题