การสร้าง rowversion แบบไม่เป็น null บน SQL Server ด้วย EF Core 3.1

Sep 02 2020

เรากำลังพยายามสร้างคอลัมน์ rowversion ที่ไม่เป็นโมฆะบน SQL Server ด้วย EF Core 3.1 โดยใช้ Fluent API:

public class Person
{
    public int Id { get; set; }
    public byte[] Timestamp { get; set; }
}

public class PersonEntityConfiguration : IEntityTypeConfiguration<Person>
{
    public void Configure(EntityTypeBuilder<Person> builder)
    {
        builder.HasKey(p => p.Id);

        builder.Property(p => p.Timestamp)
            .IsRowVersion()
            .IsRequired();
    }
}

วิธีนี้ใช้ได้ดีเมื่อทั้งตารางใหม่:

public partial class PersonMigration : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Persons",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                Timestamp = table.Column<byte[]>(rowVersion: true, nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Persons", x => x.Id);
            });
    }
}

อย่างไรก็ตามบางครั้งเราจำเป็นต้องเพิ่ม rowversion ลงในตารางที่มีอยู่ ในกรณีนั้น EF Core จะสร้างการย้ายข้อมูลที่ไม่ถูกต้อง:

public partial class PersonTimestampMigration : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<byte[]>(
            name: "Timestamp",
            table: "Persons",
            rowVersion: true,
            nullable: false,
            defaultValue: new byte[] {  });
    }
}

ค่าเริ่มต้นที่สร้างขึ้นข้างต้นจะทำให้เกิดข้อยกเว้นเมื่อนำไปใช้กับฐานข้อมูล:

ล้มเหลวในการเรียกใช้ DbCommand (1ms) [พารามิเตอร์ = [], CommandType = 'Text', CommandTimeout = '30 ']

แก้ไขตาราง [บุคคล] เพิ่ม [ประทับเวลา] rowversion ไม่เป็นค่าเริ่มต้น 0x;

Microsoft.Data.SqlClient.SqlException (0x80131904): ไม่สามารถสร้างค่าเริ่มต้นบนคอลัมน์ของการประทับเวลาชนิดข้อมูล ตาราง 'บุคคล' คอลัมน์ 'ประทับเวลา'
ไม่สามารถสร้างข้อ จำกัด หรือดัชนี ดูข้อผิดพลาดก่อนหน้านี้

นี่เป็นข้อบกพร่องที่ทราบแล้วใน EF Core หรือไม่ ปัญหานี้สามารถแก้ไขได้โดยการลบออกdefaultValue: new byte[] { }จากการย้ายข้อมูลด้วยตนเองแต่มีวิธีระงับไม่ให้สร้างค่าเริ่มต้นโดยใช้ Fluent API หรือไม่

คำตอบ

3 IvanStoev Sep 02 2020 at 17:57

นี่เป็นข้อบกพร่องที่ทราบแล้วใน EF Core หรือไม่

เป็นข้อผิดพลาด / ข้อบกพร่องอย่างแน่นอน แต่อาจไม่เป็นที่ทราบเนื่องจากเกิดขึ้นแม้ในตัวอย่างล่าสุดของ EF Core 5.0 ในขณะนี้ หรือเป็นที่รู้จักกัน แต่มีความสำคัญต่ำ (สำหรับพวกเขา) - คุณต้องตรวจสอบ EF แกนติดตามปัญหา

พยายามเพิ่มอย่างชัดเจน.HasDefaultValue(null)และ.HasDefaultValueSql(null)- ไม่มีอะไรช่วยได้ดังนั้นตัวเลือกเดียวคือการลบออกdefaultValue: new byte[] { }จากการย้ายข้อมูลด้วยตนเอง สิ่งที่ดีคือเมื่อคุณทำเช่นนั้นมันใช้งานได้และคอลัมน์จะถูกสร้างและเติมข้อมูลสำเร็จแม้ว่าตารางจะมีระเบียนอยู่แล้วก็ตาม (ซึ่งเป็นเหตุผลที่ EF Core เพิ่มdefaultValueอาร์กิวเมนต์ดังกล่าวสำหรับคอลัมน์ที่ต้องการใหม่โดยทั่วไป แต่อย่างที่เราเห็นควร t ทำเพื่อROWVERSION)