如何在实体框架中使用字符串属性作为主键

Posted

技术标签:

【中文标题】如何在实体框架中使用字符串属性作为主键【英文标题】:How to use String property as primary key in Entity Framework 【发布时间】:2016-01-04 04:06:20 【问题描述】:

我是 EF 的新手,尝试在 ETF6.0 中通过代码优先的方法完成我的第一步,现在我遇到了问题。

我有财产

[Key]
public string FooId  get; set; 

这是我的模型主键。

但是如果我运行

PM> 更新数据库

包管理器控制台中的命令更新挂起的数据库迁移我收到以下错误:

标识列“FooId”的数据类型必须为 int、bigint、smallint、 tinyint,或小数或刻度为 0 的数字,并限制为 不可为空。

如果我将模型中的 PK 更改为

[Key]
public int FooId  get; set;  

一切正常。

但我需要 PK 为字符串类型,因为它在我的情况下绝对有意义。我知道有缺点,但对我来说这是必要的。

我在这里看到了一篇较早的帖子How to make string as primary key in entity framework!。

但这似乎没有解决我的问题,或者我只是不明白。

真的不能在SQL数据库中使用字符串作为PK吗?

或者有什么办法吗?

【问题讨论】:

key默认为identity,所以需要通过属性[DatabaseGenerated(DatabaseGeneratedOption.None)]关闭,也就是说添加的时候需要手动指定key(不会生成)。 【参考方案1】:

这是在未启用身份自动增量的情况下创建 PK 的正确方法:

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string FooId  get; set; 

【讨论】:

请确保不要从DbSet<T> 继承您的表。它使脚手架创建了您未在表上定义的额外外键,并且还可能使迁移失败。我花了一天的大部分时间才弄清楚为什么会发生这种情况。【参考方案2】:

如果您需要将主键设为字符串,则不要将其设为标识列。标识列将为您生成主键值,如果您打算自己生成值,则应将其关闭。

【讨论】:

【参考方案3】:

对于不想改变他们的实体的其他人来说,另一个可能的答案是告诉 DbContext

  builder.Entity<Food>(b =>
  
       b.Property(u => u.FooId).HasDefaultValueSql("newsequentialid()");
  );

这将告诉 DbContext Food 模型有一个名为 FoodId 的 Id,它需要生成一个 ID。

EF Core 默认值:MSDN

【讨论】:

【参考方案4】:

您将字符串作为主键的原因是什么?

我只是将主键设置为一个自动递增的整数字段,并在字符串字段上放置一个索引。

这样,如果您在表上进行搜索,它们应该相对较快,并且您的所有连接和正常查找都不会影响它们的速度。

您还可以控制被索引的字符串字段的数量。换句话说,如果您认为足够的话,您可以说“仅索引前 5 个字符”。或者,如果您的数据比较相似,您可以索引整个字段。

【讨论】:

我假设他的推理与我的相同:您可以使用 .Find(fooId) od 上下文对象并应用实体框架的一级缓存我将其用于用户名

以上是关于如何在实体框架中使用字符串属性作为主键的主要内容,如果未能解决你的问题,请参考以下文章

实体框架 4.1 代码优先映射到将主键作为外键列的表

实体框架代码优先:共享主键

实体框架 6 - 数据库优先 - 缺少字符串长度属性

我应该如何编辑实体框架连接字符串?

Hibernate

如何使用实体框架将字符串映射到 Uri 类型?