如何使用Entity Framework Core配置身份列?

42

我该如何在Entity Framework Core中创建自增标识列?

很明显,我可以使用EF6的流畅API来完成。


2
我认为没有什么特别的,Id字段的默认工作方式是自增的标识列。这给你带来了问题吗? - Jeroen Vannevel
默认情况下已更改为序列。 :( - Andrew Duffy
我自己还没有使用过EF7,但是当我查看在线的示例资料时,每个模型只有一个int Id字段作为主键。 - Jeroen Vannevel
根据Rowan Miller的说法,“在EF7中将列配置为identity仍然很容易,我们只是考虑将默认设置为序列而不是identity。” 〜http://blogs.msdn.com/b/adonet/archive/2014/05/19/ef7-new-platforms-new-data-stores.aspx - Andrew Duffy
1
@AndrewDuffy,我看到有许多不同的答案随着框架的更新而改变和转移。目前,被接受的答案并不是最合适的。您是否介意进行修订和重新接受,以便指出未来读者应该优先考虑哪一个呢? - Konrad Viltersten
6个回答

54

在EF7的最新版本中,有一个新的扩展方法可以设置标识列。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{    
  modelBuilder.Entity<MyEntity>(b =>
  {
    b.HasKey(e => e.Identifier);
    b.Property(e => e.Identifier).ValueGeneratedOnAdd();
  });
}

2
注意:ValueGeneratedOnAdd并不实际设置列为Identity列,如果不是,则会失败。 - Erik Funkenbusch
与官方文档协调:HasKeyValueGeneratedOnAdd - heringer
@ErikFunkenbusch 你确定吗?我读到了这篇文章,它说ValueGeneratedOnAdd方法相当于带有Identity的DatabaseGenerated属性! - S.Serpooshan
@S.Serpooshan - 这不是官方文档。请参见ValueGeneradOnAdd的注释“这只是让EF知道对于添加或更新的实体生成值,它并不保证EF将设置实际机制来生成值。” - Erik Funkenbusch
@ErikFunkenbusch 我还没有测试过,但是当我阅读官方文档并查看其'Value generated on add'部分的更多细节时,似乎它将为标识列生成自动ID。也许该语句试图表达的是,对于特殊的数据类型(而不是整数标识),例如DateTime,我们需要为它们设置一个“默认值”,以便程序知道如何为它们生成新数据。 - S.Serpooshan
2
我刚刚检查了生成的数据库,SQL Server中的列定义为“Is Identity”= Yes。 - heringer

25

由于EF7文档十分匮乏,我们所知道的大部分信息都需要从源代码或单元测试中获取。根据EF7源代码中以下两个单元测试的描述...

这里这里

你可以像这样为Identity配置属性:

b.Property(e => e.Id).ForSqlServer().UseIdentity();

你可以这样为 Sequences 配置属性:

ForSqlServer().UseSequence();

由于 aspnet-core 重组,URL 已更改,并且此问题首次被提出以来,方法也已更改。

这里这里

if (_useSequence) 
{
    b.Property(e => e.Identifier).ForSqlServerUseSequenceHiLo();
} 
else 
{
    b.Property(e => e.Identifier).UseSqlServerIdentityColumn();
}

这些网址可能会再次更改(这就是为什么我包括相关代码的原因),但只需查看网址并转到网站即可轻松找出新网址。

实际上,我的回答的整个重点是,你可以通过查看GitHub上源代码中的单元测试来自己弄清楚这些东西。你不需要别人来指导你。

编辑:将链接更新为版本2.1(仍然适用于1.1和2.0)


我收到了这个错误,我该如何修复它?https://dev59.com/X6rka4cB1Zd3GeqPdnLf - user8280126
@AppleBook89 - 这个似乎仍在使用,你是否包含了正确的命名空间?请参阅当前的单元测试:https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.sqlserverpropertybuilderextensions.usesqlserveridentitycolumn?view=efcore-2.0 - Erik Funkenbusch
当我使用Identity列时,出现了'MissingFieldException':找不到字段的错误。我无法找到原因。我正在使用DB First方法。 - Suyash Gupta
@SuyashGupta - 这意味着预期的列名与EF所期望的不同。您可能需要手动映射它。 - Erik Funkenbusch
列名称在代码和数据库中都是相同的。当我将主键设置为标识列时,问题才会出现。如果我删除标识属性,则插入操作将顺利进行。 - Suyash Gupta
@SuyashGupta - 实际上,MissingFieldException是一个运行时异常,与数据库无关。它发生在您重新编译应用程序的一部分时,另一部分已经编译,期望类中的某个字段不再存在。我建议您重新编译应用程序中的所有内容。 - Erik Funkenbusch

24

看起来他们再次更改了方法,新的方法是:

.UseIdentityColumn()

10

在使用 EF Core 1.0 及更高版本的最新版本时,您应该使用

builder.Entity<ApplicationUser>().Property<int>(nameof(ApplicationUser.AccountNo))
            .UseSqlServerIdentityColumn()

UseSqlServerIdentityColumn是现在的做法,包括RC1 final版本,所以我想这个API会保留。 - Adam
谢谢,更新答案以明确指出RC1支持。 - codevision

6
如果您想使用 OR 运算符,或者这不是默认行为,以下是明确说明的方法。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{    
  modelBuilder.Entity<MyEntity>(b =>
  {
    b.Key(e => e.Identifier);
    b.Property(e => e.Identifier).ForSqlServer().UseIdentity();
  }
}

3

在你的模型中使用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]属性。

例如:

public class Blog
{
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public int BlogId { get; set; }

    public string Url { get; set; }
    public DateTime LastUpdated { get; set; }
}

你的例子并不反映出你的回答... - Necriis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接