如果我有这样的SQL Server表:
Location
----------
LocationId int PK
Field1 int
Field2 int
etc
Score
------------------------------------
LocationId int PK, FK
IsSingleLevel bit PK (discriminator)
Field1 int
Field2 int
etc
从技术上讲,这被映射为位置1..0 .. *分数,但是使用LocationId / IsSingleLevel的PK,它是一个位置1..0..2。
当我在EDMX上拖动它时,按预期设置所有内容(抽象实体,从基础实体中移除鉴别器等)。
EF给出了这个错误三次(一个用于基本实体,一个用于两个派生实体):
错误6错误3025:从第2146行开始映射片段时出现问题:必须指定表LocationScore的所有关键属性(LocationScore.LocationId,LocationScore.IsSingleLevelScore)的映射。
我按照示例here。
发生错误是因为我将鉴别器作为数据库中PK的一部分,并且鉴别器未映射到模型上,因此我得到了错误。
我不能将LocationId
作为PK中的唯一字段,因为那时一个位置只能有1个分数,我需要它有两个分数(一个单一级别,一个整体)。
最终结果是我希望能够做到这一点:
Locations.Include("LocationOverallScore").Single();
Locations.Include("LocationSingleLevelScore").Single();
LocationOverallScore
和LocationSingleLevelScore
是来自LocationScore
基础(抽象实体)的派生实体。
TPH不是正确的设计吗?我的数据库设计错了吗?目的是我不希望有不同分数的2个物理表 - 因为表格很大,我不想重复列。
我可以想到两种可能的解决方法:
1 - 制作一个视图(LocationScore),其中UNION是两个表(因此每个LocationId会返回2行) - 但我仍然认为我不能“TPH”这个。我不想手动执行JOIN,我想急切加载。
2 - 将IDENTITY列添加到Score,这可以是PK。
你们能想到另一种解决方案吗?
答案 0 :(得分:1)
我找到了解决方案。我不是百分之百满意,但它确实满足了我没有两张桌子的要求。
在数据库方面:
<强> LocationScore:强>
我将它导入我的EDMX - 并包含了LocationId FK(我从来没有这样做 - 但在这个例子中它是必需的)。
创建派生实体,映射字段,设置鉴别器。
在Location - &gt;之间创建关联LocationOverallScore,位置 - &gt; LocationScore(基于LocationId参考约束)。
一切正常。
一个缺点是是因为LocationId不是LocationScore表中PK的一部分,它在Location和LocationOverallScore之间是1 .. *,实际上它应该只是1 .. 1。
我通过hook属性在模型中强制执行此业务需求:
public class Location
{
// EF navigational properties - required
public ICollection<LocationOverallScore> LocationOverallScores { get; set; }
public ICollection<LocationSingleLevelScore> LocationSingleLevelScores { get; set; }
// Hook properties
public LocationOverallScore OverallScore
{
get { return LocationOverallScores.SingleOrDefault(); }
}
public LocationSingleLevelScores SingleLevelScore
{
get { return LocationSingleLevelScores .SingleOrDefault(); }
}
}
因此,如果有多条记录,.SingleOrDefault()
将抛出异常 - 由于唯一索引,它将永远不会出现。
所以我现在可以这样做:
var location = ctx.Locations.Include("LocationOverallScores").Single();
var overallScore = location.OverallScore;
这就是我现在要做的事情。