我正在学习 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
中的其他列一样。由于这也像实体中的其他属性一样被创建为列,因此可以直接添加为
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 (但在此处详细说明):
这意味着您不能随后使用以下方式进行数据库调用:
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/