如何在 EF Core 中的自动递增 table 上显式设置 ID 属性

How to explicitly set the ID property on an autoincrementing table in EFCore

我有一个模型,默认情况下它有一个自动递增的 ID 字段,这是正常的。但是,我希望用初始数据播种数据库,因为有外键,我希望明确设置播种数据的 ID。

我的模型

public class EntAttribute
{
    public int ID { get; set; }
    public string Title { get; set; }
}

我的播种代码:

public class Seeder
{
    private class AllAttributes
    {
        public List<EntAttribute> Attributes { get; set; }
    }

    public bool SeedData()
    {
        AllAttributes seedAttributes;
        string strSource;
        JsonSerializer JsonSer = new JsonSerializer();

        strSource = System.IO.File.ReadAllText(@"Data/SeedData/Attributes.json");
        seedAttributes = JsonConvert.DeserializeObject<AllAttributes>(strSource);

        _context.AddRange(seedAttributes.Attributes);
        _context.SaveChanges();
        return true;
    }
}

请注意,我对 EFCore 和 C# 都很陌生。以上是我设法拼凑的内容,在我保存更改之前它似乎一直有效。此时我得到:

SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在 table 'Attribute' 中为标识列插入显式值。

现在我足够聪明,知道这是因为我无法在 EntAttribute table 中显式设置 ID 字段,因为它想通过自动递增分配自己的 ID 字段。但是我不够聪明,不知道该怎么办。

感谢任何帮助。

编辑:根据下面接受的答案添加解决方案,因为实际代码可能会帮助其他人...

所以我在上下文 class 中添加了以下内容:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasSequence<int>("EntAttributeNumbering")
            .StartsAt(10);

        modelBuilder.Entity<EntAttribute>()
            .Property(i => i.ID)
            .HasDefaultValueSql("NEXT VALUE FOR EntAttributeNumbering");
    }

这首先确保创建了一个序列(名称是任意的),然后将其设置为用于相关的 table 而不是自动递增。完成此操作后,我就可以使用我的种子数据了。记录少于 10 条,所以我只需要将序列的起始值设置为 10。更多通常是有意义的,但我知道永远不会更多。

我还不得不对我的迁移进行闪电战,因为它们以某种方式搞得一团糟,但这可能无关紧要。

使用 EF Core,您可以创建并使用 Sequence 对象来分配 ID,并且您可以通过选择序列开始的位置来保留一系列 ID 以供手动分配。使用序列,您可以自己分配 ID,或让数据库为您完成。

仅供使用 EF Core 3 的人参考,如果您使用 int 作为您的密钥,您可以设置开始序列值,以防您有种子数据。我发现在我只有一个种子记录的用例中解决这个问题要干净得多。

例如

            modelBuilder.Entity<TableA>()
                .Property(p => p.TableAId)
                .HasIdentityOptions(startValue: 2);
            modelBuilder.Entity<TableA>()
                .HasData(
                    new TableA
                    {   
                        TableAId = 1,
                        Data = "something"
                    });

https://github.com/npgsql/efcore.pg/issues/367#issuecomment-602111259