entity-framework - 什么是自有实体?何时以及为何在 Entity Framework Core 中使用拥有的实体?

标签 entity-framework entity-framework-core

我正在学习 Entity Framework Core 。我在几乎所有教程中都遇到了 Owned Entity

这是在 Owned Entity 中使用 Entity Framework Core 的一个示例

作业实体:

public class Job : Entity
{
    public HiringManagerName HiringManagerName { get; private set; }
}

HiringManagerName 值对象:

public class HiringManagerName : ValueObject
{
    public string First { get; }
    public string Last { get; }

    protected HiringManagerName()
    {
    }

    private HiringManagerName(string first, string last)
        : this()
    {
        First = first;
        Last = last;
    }

    public static Result<HiringManagerName> Create(string firstName, string lastName)
    {
        if (string.IsNullOrWhiteSpace(firstName))
            return Result.Failure<HiringManagerName>("First name should not be empty");
        if (string.IsNullOrWhiteSpace(lastName))
            return Result.Failure<HiringManagerName>("Last name should not be empty");

        firstName = firstName.Trim();
        lastName = lastName.Trim();

        if (firstName.Length > 200)
            return Result.Failure<HiringManagerName>("First name is too long");
        if (lastName.Length > 200)
            return Result.Failure<HiringManagerName>("Last name is too long");

        return Result.Success(new HiringManagerName(firstName, lastName));
    }

    protected override IEnumerable<object> GetEqualityComponents()
    {
        yield return First;
        yield return Last;
    }
}

实体配置:

public class JobConfiguration : IEntityTypeConfiguration<Job>
{
    public void Configure(EntityTypeBuilder<Job> builder)
    {
        builder.OwnsOne(p => p.HiringManagerName, p =>
        {
            p.Property(pp => pp.First)
                .IsRequired()
                .HasColumnName("HiringManagerFirstName")
                .HasMaxLength(200);
            p.Property(pp => pp.Last)
                .IsRequired()
                .HasColumnName("HiringManagerLastName")
                .HasMaxLength(200);
        });
    }
}

这在表中创建为两列,就像 Job Entity 中的其他列一样。

enter image description here

由于这也像实体中的其他属性一样被创建为列,因此可以直接添加为 Job Entity 中的普通属性。为什么需要将其添加为 Owned Entity

请任何人都可以帮助我理解,
  • 什么是拥有实体?
  • 为什么我们需要使用拥有的实体?
  • 何时使用自有实体?
  • 最佳答案

    如果没有拥有的实体,这会是什么样子?

    如果您在 EF Core 中创建一个实体 Job ,该实体指向一个复杂对象 HiringManagerName ,在其中一个属性中,EF Core 将期望每个实体都驻留在单独的表中,并期望您定义它们之间的某种关系(例如,一对一、一对多等)。

    检索 Job 时,如果您还想显式加载 HiringManagerName 的值,则必须在查询中使用显式 Include 语句,否则将不会填充。

    var a = dbContext.Jobs
    .Include(b => b.HiringManagerName) //Necessary to populate
    .ToListAsync();
    

    但是因为每个都被认为是一个单独的实体,所以它们需要公开键,并且您必须在每个实体之间配置外键。

    什么是自有实体?

    这就是 [Owned] 类型的用武之地(参见 docs )。通过使用 [Owned] 属性标记子类,您可以将该关系的显式处理留给 EF Core 进行管理,并且不再需要在拥有的类型上定义键/外键。如果您指向您拥有的类型的集合,则相同 - 您不再需要处理任一类上的导航属性来描述关系。

    EF Core 还支持对这些拥有的类型进行查询,如下所示:
    var job = context.Jobs.Where(a => a.HiringManagerName.First == "fingers10").FirstOrDefaultAsync();
    

    现在,它带有文档中描述的两个重要的 design restrictions (但在此处详细说明):
  • 不能为拥有的类型
  • 创建 DbSet

    这意味着您不能随后使用以下方式进行数据库调用:
    dbContext.HiringManagerNames.ToListAsync();
    

    这将抛出,因为您需要简单地检索值作为调用的一部分:
    dbContext.Jobs.ToListAsync();
    

    与我给出的第一个示例不同,HiringManagerNames 不再需要显式包含,而是通过调用 Jobs DbSet<T> 返回。
  • 无法在 Entity<T>
  • 上使用拥有的类型调用 ModelBuilder
    同样,您不能在模型构建器中引用您拥有的类型来配置它。相反,如果您必须配置它,请通过针对您的 Jobs 实体和拥有的属性(property)进行配置,例如:
    modelBuilder.Entity<Job>().OwnsOne(a => a.HiringManagerNames).//Remaining configuration
    

    那么我什么时候应该使用拥有的实体?

    如果您的类型只会作为另一种类型的导航属性出现(例如,您永远不会将它本身作为查询的根实体进行查询),请使用拥有的类型以节省一些关系样板.

    如果您曾预期查询独立于父实体的子实体,请不要让它拥有它 - 它需要使用自己的 DbSet<T> 定义以便从上下文中调用。

    关于entity-framework - 什么是自有实体?何时以及为何在 Entity Framework Core 中使用拥有的实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61706738/

    相关文章:

    entity-framework - Entity Framework 6 +代码优先+ Oracle 12c的样本

    c# - 简化 Entity Framework Core 查询

    c# - System.TypeLoadException : Method 'Create' in type 'MySql.Data.EntityFrameworkCore.Query.Internal.MySQLSqlTranslatingExpressionVisitorFactory'

    .net - 如何在 .NET Entity Framework 中获取 Oracle 的下一个序列值?

    c# - EntityFramework 与 WCF - 如何返回 EF 实体

    entity-framework - Entity Framework 多对多添加/删除对象问题

    c# - 通过 ASP.NET WebMethod 在 JSON 中添加 Entity Framework 实体(一对多)

    c# - 在代码中逐一应用 EF 核心迁移

    entity-framework-core - ef7 接受字符串路径的 DbSet.Include 运算符

    c# - Entity Framework Core - 未找到设计时服务