一对一关系未加载所有实体

时间:2013-08-01 23:27:08

标签: c# entity-framework entity-framework-5

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

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

所有临时数据都会返回,但有些目标不会。这告诉我,它与在一对一中包含多个级别的导航属性有关。有没有其他人以前经历过这种行为?

2 个答案:

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