Entity Framework .NET Core 不抛出 DbUpdateConcurrencyException

问题描述 投票:0回答:1

带有从 SQL Server 数据库构建的 EF 数据集的简单 Windows 窗体程序。

如果我加载表单,该表单显示

StudentsTable
中的所有当前值,然后立即使用 SSMS 在基础 SQL Server 表中更改学生的 GPA,然后使用该表单更改学生的 GPA,它会接受更改并且不会抛出
DbUpdateConcurrencyException

这是 SQL Server 表:

我使用 Visual Studio

Scaffold-DbContext
命令根据我的数据库创建模型。

这是从数据库表创建的结果类

 public partial class StudentsTable
 {
    public int StudentId { get; set; }
    public string Fname { get; set; } = null!;
    public string Lname { get; set; } = null!;
    public decimal Gpa { get; set; }
    public int MajorId { get; set; }
    public byte[] Updated { get; set; } = null!;
    public virtual MajorTable Major { get; set; } = null!;
} 

这是

DbContext

public partial class StudentDbContext : DbContext
{
    public StudentDbContext()
    {
    }

    public StudentDbContext(DbContextOptions<StudentDbContext> options)
        : base(options)
    {
    }

    public virtual DbSet<MajorTable> MajorTables { get; set; }
    public virtual DbSet<StudentsTable> StudentsTables { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

        => optionsBuilder.UseSqlServer("xxxxxxxxxxxxx;Database=StudentDB;Trusted_Connection=True; TrustServerCertificate=True");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MajorTable>(entity =>
        {
            entity.HasKey(e => e.MajorId);

            entity.ToTable("MajorTable");

            entity.Property(e => e.MajorId).HasColumnName("MajorID");
            entity.Property(e => e.Major).HasMaxLength(50);
        });

        modelBuilder.Entity<StudentsTable>(entity =>
        {
            entity.HasKey(e => e.StudentId);

            entity.ToTable("StudentsTable");

            entity.Property(e => e.StudentId).HasColumnName("StudentID");
            entity.Property(e => e.Fname).HasMaxLength(50);
            entity.Property(e => e.Gpa)
                .HasColumnType("numeric(18, 0)")
                .HasColumnName("GPA");
            entity.Property(e => e.Lname).HasMaxLength(50);
            entity.Property(e => e.MajorId).HasColumnName("MajorID");
            entity.Property(e => e.Updated)
                .IsRowVersion()
                .IsConcurrencyToken();

            entity.HasOne(d => d.Major).WithMany(p => p.StudentsTables)
                .HasForeignKey(d => d.MajorId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_StudentsTable_MajorTable");
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

我的数据库时间戳列导致模型具有一个名为

Updated
的属性,该属性被正确标记为
IsRowVersion
IsConcurrency

这是执行更新的 C# 代码:

int newGPA;  //Variable to hold textBox input

if (int.TryParse(textBox1.Text, out newGPA))
{
    var selected = dataGridView1.CurrentRow;
    int selectedStudentId = (int)selected.Cells["StudentId"].Value;
    var selectedEvent =
        (from eachStudent in myContext.StudentsTables
            where eachStudent.StudentId == selectedStudentId
            select eachStudent).Single();
    selectedEvent.Gpa = newGPA;   //Edit one object

    try
    {
        myContext.SaveChanges();        // Save Changes
    }
    catch (Exception)
    {
        throw;
    }
}

是否需要在 C# 代码或 SQL Server 数据库中进行其他设置才能“打开”并发异常?

c# entity-framework-core
1个回答
0
投票

我几乎修好了。我编辑了

StudentDbContext
文件并更改了

entity.Property(e => e.Updated)
    .IsRowVersion()
    .IsConcurrencyToken();

entity.Property(e => e.Updated)
    .IsRowVersion()
    .IsConcurrencyToken(true);

现在,如果我运行该程序的 2 个副本,在它们都启动并显示相同的 GPA 数字之后,如果我从 1 个副本更新 GPA,然后从第 2 个副本更新相同的值,而不是例外,第 2 个副本“赢”,但是如果我继续从其中任何一个进行更新,此后每次都会正确抛出 DbUpdateConcurrencyException。为什么第一次没有检测到,但之后就可以工作了,这是一个新的谜团。

© www.soinside.com 2019 - 2024. All rights reserved.