[英]The EF Core child entity isn't loaded along with the parent
我正在处理带有两个表的 SQL Server 数据库: INVOICE_HEADER
和INVOICE_ROW
。 INVOICE_HEADER
有两个字段:
INTERNAL_ID
,输入int
和主键,INV_NUM
,类型varchar(13)
,它对每个业务逻辑是唯一的,但不是每个数据库结构。 INVOICE_ROW
有三个:
INTERNAL_ID
,输入int
和主键,INV_NUM
,输入varchar(13)
,INV_ROW_NUM
,类型int
,每个业务逻辑也是唯一的。 INVOICE_ROW
中INV_NUM
值与INVOICE_HEADER
的一行具有相同值的INV_NUM
业务逻辑术语中构成相同的发票,因此INVOICE_HEADER.INV_NUM
和( INVOICE_ROW.INV_Num
, INVOICE_ROW.INV_ROW_NUM
)就我们的查询而言充当事实上的主键担心的。
在找到的值INVOICE_HEADER.INTERNAL_ID
是从那些在发现的不同INVOICE_ROW.INTERNAL_ID
,并在两个表中没有字段似乎有对应于该值INTERNAL_ID
在其他。
所以没有实际的外键将任一表链接到另一个表。
我需要提到数据库来自第三方,它的结构是固定的,它有更多的表,并且INVOICE_HEADER
和INVOICE_ROW
都有更多的字段? 无论如何,我刚刚做到了。
实际上, INTERNAL_ID
甚至几乎没有出现在描述数据库结构的文档中,逐个字段,并且仅用于其他一些表。
由于上述原因,我无法使用数据库中定义的主键。
所以我创建了两个类:
public class InvoiceHeader
{
public int InternalId { get; set; }
public string InvoiceNum { get; set; }
public virtual List<InvoiceRow> InvoiceRows { get; set; }
}
public class InvoiceRow
{
public int InternalId { get; set; }
public string InvoiceNum { get; set; }
public int? RowNum { get; set; }
public virtual InvoiceHeader InvHeader { get; set; }
}
和上下文:
public DbSet<InvoiceHeader> RepoInvHeader { get; set; }
public DbSet<InvoiceRow> RepoInvRow { get; set; }
protected override void OnModelCreating(ModelBuilder p_mbuModel)
{
base.OnModelCreating(p_mbuModel);
// Table name
p_mbuModel.Entity<InvoiceHeader>().ToTable("INVOICE_HEADER");
// Primary key
p_mbuModel.Entity<InvoiceHeader>().HasKey(t => new { t.InternalId }).
HasName("PK_INTERNAL_ID_INVOICE_HEADER");
// Fields
p_mbuModel.Entity<InvoiceHeader>().Property(t => t.InternalId).IsRequired();
p_mbuModel.Entity<InvoiceHeader>().Property(t => t.InternalId).HasColumnType("int");
p_mbuModel.Entity<InvoiceHeader>().Property(t => t.InvoiceNum).HasColumnName("INV_NUM");
p_mbuModel.Entity<InvoiceHeader>().Property(t => t.InvoiceNum).HasColumnType("varchar(13)");
p_mbuModel.Entity<InvoiceHeader>().Property(t => t.InvoiceNum).HasMaxLength(13);
// Foreign keys
p_mbuModel.Entity<InvoiceHeader>().HasMany(h => h.InvoiceRows).
WithOne(r => r.InvHeader).
HasPrincipalKey(h => h.InvoiceNum).
HasForeignKey(r => r.InvoiceNum);
// Table name
p_mbuModel.Entity<InvoiceRow>().ToTable("INVOICE_ROW");
// Primary key
p_mbuModel.Entity<InvoiceRow>().HasKey(t => new { t.InternalId }).
HasName("PK_INTERNAL_ID_INVOICE_ROW");
// Fields
p_mbuModel.Entity<InvoiceRow>().Property(t => t.InternalId).IsRequired();
p_mbuModel.Entity<InvoiceRow>().Property(t => t.InternalId).HasColumnType("int");
p_mbuModel.Entity<InvoiceRow>().Property(t => t.InvoiceNum).HasColumnName("INV_NUM");
p_mbuModel.Entity<InvoiceRow>().Property(t => t.InvoiceNum).HasColumnType("varchar(13)");
p_mbuModel.Entity<InvoiceRow>().Property(t => t.RowNum).HasColumnName("INV_ROW_NUM");
p_mbuModel.Entity<InvoiceRow>().Property(t => t.RowNum).HasColumnType("int");
// Foreign keys
p_mbuModel.Entity<InvoiceRow>().HasOne(r => r.InvHeader).
WithMany(h => h.InvoiceRows).
HasForeignKey(r => r.InvoiceNum).
HasPrincipalKey(h => h.InvoiceNum);
}
我觉得所有提到的HasMany
, WithOne
都是必要的,以弥补缺乏真正可用的主键。
我尝试了以下方法:
InvoiceHeader z_objHeader = z_dbcContexteSage.repoInvHeader.Include(h => h.InvoiceRows).FirstOrDefault(h => h.Piece == "XXXX");
在调试时, z_objHeader
适当地具有我期望来自INVOICE_HEADER
的字段的值,但其InvoiceRows
属性为null
。 (我也试过foreach (InvoiceRow z_objRow in z_objHeader.InvoiceRows)
:它抛出一个NullReferenceException
。)
现在,如果我添加并运行它,
InvoiceRow z_objRow = z_dbcContexteSage.repoInvRow.FirstOrDefault(r => r.Piece == "XXXX");
查看z_objHeader.InvoiceRows
表明它现在包含一个InvoiceRow
。
更好的是,运行后
List<InvoiceRow> z_lisRows = z_dbcContexteSage.repoInvRow.Where(r => r.Piece == "XXXX").ToList();
z_objHeader.InvoiceRows
现在拥有我希望它拥有的所有行。
所以我可以使用它,但我仍然觉得那些从INVOICE_ROW
显式加载的命令是不需要的,甚至不需要。
我在网络上四处张望,似乎无法找出我忽略或遗漏的内容。
我想问题可能在于官方但无法使用的主键/事实上的主键。
有任何想法吗?
这不是我忘记放入的东西,而是我(或其他人)在某个时候放入的东西。
有一个
using System.Data.Entity;
在测试类中,这显然弄乱了Update()
方法。 现在它消失了,属性InvoiceRows
已正确加载。
感谢所有花时间阅读问题的人!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.