2

我有一个(由于合同约束而设计的和过度简化的)数据模型,应该如下所示:

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();

所有临时数据都回来了,但有些目的地没有。这向我暗示,它与在一对一中包含多个级别的导航属性有关。以前有没有其他人经历过这种行为?

4

2 回答 2

0

我之前遇到过问题,我的解决方案是使用 1:many 因为如果 POCOA 包括 POCOB

.Include(x => x.POCOA.POCOB) 

真正将 POCOB 作为列表返回,因为我们知道它 100% 返回一条记录,那么在获取数据的过程中,我们可以说 a.SingleOrDefault();

于 2013-08-02T03:00:52.080 回答
0

除了共享主键 1:1 关联情况外,EF 不正式支持 1:1 关联。

您正在做的是创建 1:many's 并试图告诉 EF 这实际上是 1:1。问题是,db 模式实际上是 1:many 模式,EF 在这里会出现问题。

如果您的要求是 1:1,那么您需要使用共享主键(两个实体具有相同的主键),并且一个也将其视为外键)。

于 2013-08-02T01:43:31.183 回答