c# - EF core 3.1 - 实体和拥有类型的公用表
问题描述
我试图在我的项目中实现 DDD 方法,但意识到我的聚合太大,并试图最大限度地减少从数据库加载的数据量。我有一个聚合订单,在某些操作期间它依赖于另一个聚合公司。要执行RefreshOrderNumber()操作,我需要来自 Company 实体的三个属性,并且对 **Company 的其他字段完全不感兴趣。所以,我想到了为 Order - OrderCompanyInfo创建一个值类型并将这些字段封装在上面
public class Company
{
public Id {get;private set;}
public string Name {get; private set;}
public string Currency {get; private set;}
public string DocumentPrefix {get; private set;}
// other ~15 fields
}
public class OrderCompanyInfo : ValuableType
{
private OrderCompanyInfo ()
{
}
public long CompanyId {get; private set;}
public string Name {get; private set;}
public string Currency {get; private set;}
public string DocumentPrefix {get; private set;}
public static OrderCompanyInfo Create(Company company)
{
return OrderCompanyInfo {
CompanyId = company.Id,
Name = company.Name,
Currency = company.Currency ,
DocumentPrefix = company.DocumentPrefix
}
}
}
public class Order
{
private Order()
{
}
public Order(OrderCompanyInfo companyInfo)
{
CompanyInfo = companyInfo;
AddLog();
}
public OrderNumberInfo OrderNumber {get; private set;}
public OrderCompanyInfo CompanyInfo {get; private set;}
public void DoSomethingImportant()
{
RefreshOrderNumber();
AddLog();
}
private void AddLog()
{
//Add log entry using CompanyInfo.Name
}
private void RefreshOrderNumber()
{
//Create new OrderNumberInfo using OrderCompanyInfo.Currency and OrderCompanyInfo.DocumentPrefix
}
}
现在我正在尝试使它与 EF 核心一起工作。基本上OrderCompanyInfo应该使用OwnOne()方法配置并映射到与Company实体相同的表,因此在通过存储库加载 Order 聚合期间数据始终是实际的。所以我对 Order 聚合有这个配置:
public override void Configure(EntityTypeBuilder<Order> builder)
{
builder.OwnsOne(x => x.InventoryOwnsCompanyProfile, opt =>
{
opt.ToTable("Company");
opt.HasOne<Company>()
.WithOne()
.HasForeignKey<OrderCompanyInfo>(x => x.CompanyId);
});
}
但是尝试这种方式会给我一个错误:
Cannot use table 'dbo.Company' for entity type 'OrderCompanyInfo ' since it is being used for entity type 'Company' and there is no relationship between their primary keys.
有没有办法让 EF 核心以这种方式工作?
解决方案
好的,在 GitHub 社区上找到了答案。 https://github.com/dotnet/efcore/issues/13162#issuecomment-417411405
他们提供了一个示例,其中包含两个映射到同一张表的实体
namespace One
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}
namespace Two
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Birthday { get; set; }
}
}
public class BloggingContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0");
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<One.Person>(b =>
{
b.HasOne<Two.Person>().WithOne().HasForeignKey<Two.Person>(e => e.Id);
b.ToTable("People");
b.Property(e => e.Name).HasColumnName(nameof(One.Person.Name));
});
builder.Entity<Two.Person>(b =>
{
b.ToTable("People");
b.Property(e => e.Name).HasColumnName(nameof(Two.Person.Name));
});
}
}
我试图将OrderCompanyInfo构建为拥有类型是错误的,因为拥有类型意味着拥有类型与所有者之间的关系。在我的场景中,这将导致Company表将具有OrderId字段的情况,这至少是不正确的。通过 HasOne() 配置 OrderCompanyInfo 实体非常适合我
推荐阅读
- python - 创建数据透视表时忽略值的索引
- java - 我可以在不使用管理控制台的情况下获取 JMS 队列详细信息吗?
- javascript - 如何在 Angular js 循环中绑定“名称属性”
- c++ - 使用 sizer 调整 wxListView 的大小
- javascript - 表单验证期间的 PHP 错误处理
- python - 在 Django 中显示用户生成的视频
- html - 将用于输入注释的文本区域列带到表单中其他列的相同列位置
- firefox - 规则选择器的一部分是黄色的
- c++ - 如何为具有默认值的构造函数中的枚举赋值?
- asp.net-core - 传递到 ViewDataDictionary 的模型项属于“MainModel”类型,但此 ViewDataDictionary 实例需要一个“testModel”类型的模型项