![](/img/trans.png)
[英]How to create one-to-one relationship in Entity Framework Core?
[英]One-to-One relationship in Entity Framework Core
在过去的几周里,我一直在研究 .NET Core,并决定尝试使用 EF Core(来自 ASP.NET MVC with NHibernate)。 经过一番挖掘后,我发现了一个名为EF Visual Designer的不错的扩展。 它允许我直观地创建 model 并生成代码。
我已经定义了图中所示的简单一对一关系: Simple one-to-one relationship
生成代码后,我得到以下 Fluent API 代码:
modelBuilder.Entity<Authentication>()
.ToTable("Authentications")
.HasKey(t => t.Id);
modelBuilder.Entity<Authentication>()
.Property(t => t.Id)
.IsRequired()
.ValueGeneratedOnAdd();
modelBuilder.Entity<User>()
.ToTable("Users")
.HasKey(t => t.Id);
modelBuilder.Entity<User>()
.Property(t => t.Id)
.IsRequired()
.ValueGeneratedOnAdd();
modelBuilder.Entity<User>()
.HasOne(x => x.Authentication)
.WithOne()
.HasForeignKey("Authentication_Id")
.IsRequired();
用户 class 具有以下(相关)属性:
public Class User {
[Key]
[Required]
public Guid Id { get; set; }
...
public virtual Authentication Authentication { get; set; }
}
身份验证具有以下(相关)属性:
public class Authentication {
[Key]
[Required]
public Guid Id { get; set; }
}
但是,当我尝试生成迁移时,出现以下错误:
您正在配置“User”和“Authentication”之间的关系,但在“Authentication_Id”上指定了一个外键。 必须在作为关系一部分的类型上定义外键。
我尝试切换到多对一关系并且没有任何问题。 这可能是一种解决方法,但不是一个非常干净的方法。 这可能是由于命名问题导致的,例如两个实体都将“Id”作为主键?
如果是这样,什么是“最佳实践”? 我是否为每个实体提供了唯一的 ID 列名称? 我如何 go 关于派生类都继承 ID 列的抽象实体?
您需要将外键放在另一个类上。 看来您在Authentication类上没有属性“ Authentication_Id”。
我从未使用过EF Visual Designer来生成代码,而只是通过查看您的代码,要么User
实体需要Authentication
的外键,要么Authentication
实体需要User
的外键。
假设您要将外键放在User
:
public class User
{
[Key]
[Required]
public Guid Id { get; set; }
public Guid AuthenticationId { get; set; }
// Even this navigation property is optional
// for configuring one-to-one relationship
public virtual Authentication Authentication { get; set; }
}
public Authentication
{
[Key]
[Required]
public Guid Id { get; set; }
}
然后,一对一关系应配置为:
modelBuilder.Entity<User>()
.HasOne(x => x.Authentication)
// Or like this if you don't have Authentication navigation property:
//.HasOne<Authentication>()
.WithOne()
.HasForeignKey(x => x.AuthenticationId);
不,您不必为每个实体赋予唯一的ID列名称。 实际上,您可以在代码中调用任何内容,然后在配置中将其重命名:
modelBuilder.Entity<User>()
.Property(x => x.Id).HasColumnName("WHATEVER_YOU_WANT_TO_CALL_IN_DB");
到目前为止所有做出回应的人都是对的。 您在依赖实体中缺少一个外键,因此您需要添加一个。 根据您的代码,它必须是“Authentication_Id”,因为这是您引用的名称——但您实际上没有声明一个!
其次, Vladislav Vazhenin是对的:
尝试在.HasForeignKey(x => x.AuthenticationId) 上构建时出错; 但是.HasForeignKey <User> (x => x.AuthenticationId); 为我工作
只需确保您指向导航属性而不是关联的实体密钥属性(Authentication 与 AuthenticationId)。 所以,考虑一下。
事实上,有人需要推动文档(似乎是用户编辑的)来包含这些细微的差异。 例如; .HasOne也有一个变种
.HasOne(x=>x.Authentication)
和
.HasOne<Authentication>()
包括一条注释,说明它们是否因 Entity Framework Core 的版本而异。 编译器有时会阻止或忽略其中一些可有可无或已弃用的命令变体。 但是我们需要知道哪个适用于哪个版本,以及流利的 api 覆盖数据注释是如何工作的(强调哪个优先)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.