问题描述
数据库
我正在使用带有两个表的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
值,因此在业务逻辑方面构成相同的发票,因此INVOICE_HEADER.INV_NUM
和({{1 }},INVOICE_ROW.INV_Num
)就我们的查询而言实际上是主键。
在INVOICE_ROW.INV_ROW_NUM
中找到的值与在INVOICE_HEADER.INTERNAL_ID
中找到的值不同,并且两个表中的任何字段似乎都不具有与另一个表中INVOICE_ROW.INTERNAL_ID
对应的值。
因此,没有实际的外键将任何一个表链接到另一个表。
我是否需要提及数据库来自第三方,其结构是固定的,具有更多表以及INTERNAL_ID
和INVOICE_HEADER
都具有更多字段?好吧,无论如何我还是这么做的。
实际上,INVOICE_ROW
甚至几乎没有出现在描述数据库结构的文档中(逐字段,仅针对其他一些表)。
使用Entity Framework Core访问数据库
由于上述原因,我无法使用数据库中定义的主键。
所以我创建了两个类:
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
显式加载的命令不是必需的,甚至是有用的。
我在网络上看了很多遍,似乎找不到我忽略或遗忘的地方。
我想抓住的可能是那些官方但无法使用的主键/事实上的主键东西。
有什么想法吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)