所以我稍微深入EF Core并尝试继承和TPH模式(我之前没有经验)。 EF创建的结果数据库不是我所期望的,我想知道是否可以使用fluent-api获得我想要的结果,或者我是否完全忽略了这一点。
首先,这是我的POCO课程:
public class Commission
{
public int Id { get; set; }
public string Description { get; set; }
public double Rate { get; set; }
}
public class Party
{
public int PartyId { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
public class Agency : Party
{
public string AgencyCode { get; set; }
public ICollection<Commission> Commissions { get; set; }
}
public class Carrier : Party
{
public string CarrierCode { get; set; }
public ICollection<Commission> Commissions { get; set; }
}
public class Principal : Party
{
public string Website { get; set; }
public string DistrictCode { get; set; }
}
我的上下文类以防万一:
public class PartyContext : DbContext
{
public DbSet<Agency> Agencies { get; set; }
public DbSet<Carrier> Carriers { get; set; }
public DbSet<Party> Parties { get; set; }
public DbSet<Commission> Commissions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=LAPTOP-PC\SQLEXPRESS;Database=MyDatabase;Trusted_Connection=True;");
}
}
基本上,代理商,承运人和委托人都是从党继承的,所以他们应该拥有与党相同的所有财产。代理商和承运人具有其他特定属性,并且与委员会之间应具有零或一对多的关系。此外,Principal有几个特定属性,但与佣金无关。
我对Parties表本身的输出没有任何问题,并且理解鉴别器字段是什么,但是我不理解它创建的两个外键关系:
我的问题是为什么我不能在后端与委员会_PartyId之间建立一个外键关系?如果可以的话,我如何告诉EF以这种方式创建它?
修改
使用Dmitry的建议并使用[InverseProperty]属性,我最终得到了以下数据库设计,这不是所需的输出:
它实际上是第三个字段(PartyId1)。所以我开始再次查看EF documentation on relationships并开始使用不同的注释。使用[ForeignKey(&#34; PartyId&#34;)]属性给我带来了一些希望,因为它产生了我期待的设计:
然而,这也有一些意想不到的效果。在尝试使用Agency和Carrier填充数据库之后,我收到了一个例外。
这是填充代码:
PartyContext _context = new PartyContext();
// Add an Agency
var agencyCommission1 = new Commission
{
Description = "Contract",
Rate = 0.075
};
var agencyCcommission2 = new Commission
{
Description = "Hauling",
Rate = 0.10
};
var agencyCommissionList = new List<Commission>
{
agencyCommission1, agencyCcommission2
};
var agency = new Agency
{
Name = "Agency International",
Address1 = "12345 Main Street",
Address2 = "Suite 100",
City = "Chicago",
State = "IL",
Zip = "31202",
AgencyCode = "AI",
Commissions = agencyCommissionList
};
// Add Carrier
var carrierCommission1 = new Commission
{
Description = "Coal",
Rate = 0.15
};
var carrierCommission2 = new Commission
{
Description = "Mining",
Rate = 0.115
};
var carrierCommissionList = new List<Commission>
{
carrierCommission1, carrierCommission2
};
var carrier = new Carrier
{
Name = "Carrier International",
Address1 = "54321 Main Street",
Address2 = "Suite 300",
City = "Cleveland",
State = "OH",
Zip = "44115",
CarrierCode = "CI",
Commissions = carrierCommissionList
};
_context.Agencies.Add(agency);
_context.Carriers.Add(carrier);
try
{
_context.SaveChanges();
}
catch(Exception ex)
{
return;
}
添加代理商时的例外情况是&#34;无法投放类型&#39; EFTest.Agency&#39;输入&#39; EFTest.Carrier&#39;。&#34;尝试添加运营商时的例外情况是&#34;无法投射类型&#39; EFTest.Carrier&#39;输入&#39; EFTest.Agency&#39;。&#34;
我将补充说,在使用原始EF设计时,程序确实按预期工作,但是额外的字段和外键使我的强迫症有点疯狂:)欢迎任何更多的想法!
答案 0 :(得分:4)
如果将两个关系配置为使用与外键相同的属性,则仍然有两个关系。因此,当添加Commission
PartyId
等于1 EF时,将其解释为与Agency
相关,PartyId
等于1 且 a { {1}} Carrier
等于1,显然这是不可能的。
您需要做的是在PartyId
和Commission
之间建立关系,但这意味着需要将Party
导航属性移至Commissions
同样。但是,您仍然可以将其隐藏在Party
和其他派生类上,方法是将其隐藏起来并仅在Principal
和Agency
上公开:
Carrier
答案 1 :(得分:0)
试试这个:
public class Commission
{
public int Id { get; set; }
public string Description { get; set; }
public double Rate { get; set; }
public Party Party { get; set; } // <-- "parent" party link here
}
public class Agency : Party
{
public string AgencyCode { get; set; }
[InverseProperty("Party")] // <-- link this collection with Party.Party
public ICollection<Commission> Commissions { get; set; }
}
public class Carrier : Party
{
public string CarrierCode { get; set; }
[InverseProperty("Party")] // <-- link this collection with Party.Party
public ICollection<Commission> Commissions { get; set; }
}