c# - EF Core 中的一对零或一对一关系

标签 c# entity-framework-core

让我简化一下:

给定两个模型

部门模型

    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/

相关文章:

c# - 为可观察集合实现中介设计模式

c# - 特殊字符的正则表达式?

c# - 查询需要在 .ThenInclude 之后过滤,使用 .Where 子句

c# - 自托管 Owin 端点中的客户端证书映射身份验证

sql-server - 使用 .net Core/EF Core 在 SQL Server 2016 中的 ASP MVC 应用程序中进行列加密

c# - 无法按索引访问 DataGridViewRow 单元格

sql-server - 无法从 Docker 容器连接到 SQL Server

c# - "the term ' 添加迁移 ' is not recognized as the name of a cmdlet" Visual Studio 2019

asp.net-mvc - .NET Core Entity Framework 在作为实体访问时抛出无效的对象名称,但适用于 SQL

c# - Entity Framework Core 中的条件导航属性