我有一个(设计和过度简化,由于合同约束)数据模型应该如下所示:
public class ProvisionalData
{
public int ProvisionalDataID { get; set; }
public string Data { get; set; }
public Lot Lot { get; set; }
}
public class Destination
{
public int DestinationID { get; set; }
public string Name { get; set; }
}
public class LotDestination
{
public int LotDestinationID { get; set; }
public int DestinationID { get; set; }
public DateTime Month { get; set; }
public Destination Destination { get; set; }
}
public class Lot
{
public int LotID { get; set; }
public int ProvisionalDataID { get; set; }
public int LotDestinationID { get; set; }
public ProvisionalData ProvisionalData { get; set; }
public LotDestination LotDestination { get; set; }
}
从Lot到ProvisionalData的关系是双方必需的一对一关系。请注意,这不是整个模型,也不是关注的域。关注的是配置一对一的关系。
我与一对一的映射流畅配置相关:
public class LotConfig : EntityTypeConfiguration<Lot>
{
public LotConfig()
{
ToTable("Lot");
HasKey(x => x.LotID);
HasRequired(x => x.ProvisionalData)
.WithRequiredDependent(x => x.Lot)
.WillCascadeOnDelete(true);
}
}
public class ProvisionalDataConfig : EntityTypeConfiguration<ProvisionalData>
{
public ProvisionalDataConfig()
{
ToTable("ProvisionalData");
HasKey(x => x.ProvisionalDataID);
}
}
显示的其他关系实际上已经设置 - 我已经验证它们是在我的上下文中配置的,并且所有IDbSets都存在且运行正常。实际上,除了导航属性上的某些ProvisionalData实体不会被以下查询填充外,所有内容都“适用”此设置:
var lotDestination = db.lotDestinations
.Where(x => x.DestinationId == destinationId && x.Month == month)
.Include(x => x.Lots)
.Include("Lots.ProvisionalData")
.Include(x => x.Destination)
.SingleOrDefault();
在我的真实数据集中,此查询将返回30 Lots的目标。这些批次中的16个已加载其ProvisionalData导航属性。 14不要。当我手动循环遍历每个批次并db.Entry(lot).Reference(ProvisionalData).Load()
时,此问题仍然存在。当我检查这些条目时,所有30个条目都会true
返回.IsLoaded
。查询和.Includes
似乎正在做他们应该做的事情,但是有些实体由于我不理解的原因而没有回来。我希望这是一件我看不见的简单事情,因为我已经盯着它看了太久。
但是,当我将关系(忽略现有的数据库约束)更改为一对多的ProvisionalData实体时,如下所示:
public class ProvisionalData
{
public int ProvisionalDataID { get; set; }
public string Data { get; set; }
public IList<Lot> Lots { get; set; }
}
以及像这样的新Lot配置:
public class LotConfig : EntityTypeConfiguration<Lot>
{
public LotConfig()
{
ToTable("Lot");
HasKey(x => x.LotID);
HasRequired(x => x.ProvisionalData)
.WithMany(x => x.Lots)
.HasForeignKey(x => x.ProvisionalDataID);
}
}
一切都完美无瑕。这里唯一的缺点是,这并没有反映数据库中的真正约束,因此您可以在技术上尝试将多个Lots添加到同一个ProvisionalData,这在尝试保存时会中断。我可以自己构建逻辑来防止这种情况,但为什么我不能在Entity Framework中表达它呢?我的配置不正确吗?
另外有趣的是,当我将上述查询切换到这个哑版本来测试时(在EF中仍然存在一对一的映射):
var quota = db.Lots
.Where(l => l.LotDestination.DestinationID == destinationId && l.LotDestination.Month == m)
.Include(x => x.ProvisionalData)
.Include(x => x.LotDestination)
.Include(x => x.LotDestination.Destination)
.Select(x => x.LotDestination)
.FirstOrDefault();
所有临时数据都会返回,但有些目标不会。这告诉我,它与在一对一中包含多个级别的导航属性有关。有没有其他人以前经历过这种行为?
答案 0 :(得分:0)
EF不正式支持除共享主键1:1关联情况之外的1:1关联。
你正在做的是创造1:很多,并试图告诉EF它真的是1:1。问题是,db模式实际上是1:许多模式,而EF在这里会遇到问题。
如果您的要求是1:1,那么您需要使用共享主键(两个实体具有相同的主键),并且还需要将其视为外键。
答案 1 :(得分:0)
我之前遇到的问题,我的解决方案是使用1:很多,因为如果POCOA包含POCOB
.Include(x => x.POCOA.POCOB)
确实将POCOB作为列表返回,因为我们知道它100%返回一条记录,然后在获取数据期间,我们可以说a.SingleOrDefault();