让我简化一下:
给定两个模型
部门
模型
public Guid Id { get; set; }
public string DepartmentID { get; set; }
public string DepartmentName { get; set; }
public Guid? DepartmentManager { get; set; }
员工
模型
public Guid ID { get; set; }
public string EmployeeID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
我希望能够指定一名(且仅有一名)员工作为该部门的部门经理。
示例:部门是财务。部门经理是 Joe Blow。
部门模型中的 DepartmentManager 应包含员工模型中 Joe Blow 的 EmployeeID
我认为一旦模型中的关系正确,我将能够完成 cshtml 页面以正确处理 CRUD。
谢谢, 约翰
最佳答案
假设这些是您的模型类:
public class Department
{
public Guid Id { get; set; }
public string DepartmentID { get; set; }
public string DepartmentName { get; set; }
public Guid? DepartmentManager { get; set; }
}
和
public class Employee
{
public Guid ID { get; set; }
public string EmployeeID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
}
您有几个选项可用于显式配置实体(数据模型)之间的关系。
1。数据属性
如果您对 Fluent API 不满意,您可以使用数据属性来装饰模型,EF 在内存中构建模型时会发现并使用这些数据属性。因此,对于您的情况,类似这样的方法是有效的:
[Table(nameof(Department))]
public class Department
{
[Key]
public Guid Id { get; set; }
public string DepartmentID { get; set; }
public string DepartmentName { get; set; }
[ForeignKey(nameof(DepartmentManager))]
public Guid? DepartmentManagerID { get; set; }
public virtual Employee DepartmentManager { get; set; }
}
和
[Table(nameof(Employee))]
public class Employee
{
public Employee()
{
Departments = new HashSet<Department>();
}
[Key]
public Guid ID { get; set; }
public string EmployeeID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public virtual ICollection<Department> Departments { get; set; }
}
TableAttribute
是可选的 - 我用它来明确声明该表使用单数命名约定(因此该表称为“Department”,而不是“Departments”)。 KeyAttribute
也应该是可选的,因为 EF 的约定之一是假设“ID”字段是主键,但是,[Key]
再次使其显式化(感知)这里有一个主题吗?)。
我还建议使用 DepartmentManagerID
作为外键属性,而不是 DepartmentManager
,以保持一致。您还可以添加导航属性 DepartmentManager
,该属性可用于在查询部门时包含员工记录。
Employee
可以(应该?)也有一个导航属性 Departments
,它代表 Employee 之间“一对多”关系的“多”方和部门 - 一个部门只能有一个员工(经理),但一个员工可以管理多个部门。将此属性设置为虚拟
属性允许 EF 延迟加载该属性,因此您可以查询员工记录,而不必总是获取关联的部门。
2。流畅的API
除了数据属性之外,还可以使用 Fluent API,或者就地使用(您的选择)。我仍然会添加相关的导航属性,因此您的模型将如下所示:
public class Department
{
public Guid Id { get; set; }
public string DepartmentID { get; set; }
public string DepartmentName { get; set; }
public Guid? DepartmentManagerID { get; set; }
public virtual Employee DepartmentManager { get; set; }
}
和
public class Employee
{
public Employee()
{
Departments = new HashSet<Department>();
}
public Guid ID { get; set; }
public string EmployeeID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public virtual ICollection<Department> Departments { get; set; }
}
然后,在您的 DbContext 类中(为了保持简单),您将配置模型及其关系:
public partial class JohnsDbContext : DbContext
{
public JohnsDbContext(DbContextOptions<JohnsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// To set the table name, uncomment:
//modelBuilder.Entity<Department>()
// .ToTable(nameof(Department));
modelBuilder.Entity<Department>()
.HasKey(m => m.ID);
modelBuilder.Entity<Department>()
.HasOne(m => m.DepartmentManager) // Department.DepartmentManager
.WithMany(m => m.Departments) // Employee.Departments
.HasForeignKey(m => m.DepartmentManagerID); // Department.DepartmentManagerID
modelBuilder.Entity<Employee>()
.HasKey(m => m.ID);
}
}
这几乎是使用 Fluent API 建立关系的最低要求。还有更多可用设置,如果您需要,Intellisense 将帮助您发现这些设置。
关于c# - EF Core 中的一对零或一对一关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66846195/