我有一个(由于合同约束而设计的和过度简化的)数据模型,应该如下所示:
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);
}
}
显示的其他关系实际上已设置 - 我已验证它们正在我的上下文中进行配置,并且所有 IDbSet 都存在并正常运行。事实上,除了导航属性上的一些临时数据实体没有由以下查询填充之外,一切都“适用”此设置:
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 个批次的目的地。其中 16 个地块加载了它们的临时数据导航属性。14 没有。当我手动循环遍历每个 Lot 和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; }
}
和这样的新批次配置:
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);
}
}
一切都完美无缺。这里唯一的缺点是这并不能反映数据库中的真正约束,因此您可以在技术上尝试将多个批次添加到同一块临时数据中,这会在尝试保存时中断。我可以自己构建逻辑来防止这种情况发生,但是为什么我不能在实体框架中表达它呢?我的配置不正确吗?
同样有趣的是,当我将上述查询切换到这个哑版本来测试事物时(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();
所有临时数据都回来了,但有些目的地没有。这向我暗示,它与在一对一中包含多个级别的导航属性有关。以前有没有其他人经历过这种行为?