简体   繁体   English

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

[英]One-to-One Relationship Not Loading All Entities

I have a (contrived and over-simplified, due to contractual constraints) data model that should look like this: 我有一个(由于合同约束,人为地简化了)数据模型应如下所示:

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; }
}

The relationship from Lot to ProvisionalData is a required one-to-one on both sides. 双方都必须一对一地建立从Lot到ProvisionalData的关系。 Please note, this is not the whole model, nor is the domain the concern. 请注意,这不是整个模型,也不是您所关注的领域。 The concern is with configuring the one-to-one relationship. 关注的是配置一对一关系。

My relevant to the one-to-one mapping fluent configurations: 我与一对一映射流利的配置有关:

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

The other relationships shown are in fact set up - I have verified that they are being configured in my context, and all IDbSets exist and function correctly. 显示的其他关系实际上已经建立-我已经验证了它们是在我的上下文中配置的,并且所有IDbSet存在并且可以正常运行。 In fact, everything "works" with this setup, except that some ProvisionalData entities on navigation properties are not populated by the following query: 实际上,除了以下查询未填充导航属性上的某些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();    

In my real dataset, this query will return a destination with 30 Lots. 在我的真实数据集中,此查询将返回30手的目的地。 16 of those lots have their ProvisionalData navigation property loaded. 这些批次中的16个已加载其ProvisionalData导航属性。 14 do not. 14不。 This problem persists when I manually loop through each Lot and db.Entry(lot).Reference(ProvisionalData).Load() . 当我手动遍历每个Lot和db.Entry(lot).Reference(ProvisionalData).Load()时,此问题仍然存在。 When I examine those entries, all 30 return true for .IsLoaded . 当我检查这些条目时, .IsLoaded所有30个都返回true The query and .Includes appears to be doing what they are supposed to, but some of the entities aren't coming back for reasons I don't understand. 查询和.Includes似乎在执行它们应该做的事情,但是由于我不了解的原因,一些实体没有回来。 I'm hoping it's something simple that I can't see because I've been staring at it for too long. 我希望这是我看不到的简单事物,因为我盯着它看了太久了。

However, when I change the relationship (ignoring existing database constraints) to a one-to-many with ProvisionalData entities looking like this: 但是,当我将ProvisionalData实体的关系(忽略现有数据库约束)更改为一对多时,如下所示:

public class ProvisionalData
{
public int ProvisionalDataID { get; set; }
public string Data { get; set; }

public IList<Lot> Lots { get; set; }
}

and a new Lot configuration like this: 以及新的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);
    }
}

everything works flawlessly. 一切正常。 The only drawback here is that this doesn't reflect the true constraints in the database, so you could technically try to add multiple Lots to the same piece of ProvisionalData, which would break when trying to save. 唯一的缺点是,这并不能反映数据库中的真正约束,因此您可以从技术上尝试将多个批次添加到同一临时数据中,这在尝试保存时会中断。 I can build the logic in to prevent this myself, but why can't I express it here in Entity Framework? 我可以建立逻辑来防止这种情况发生,但是为什么我不能在Entity Framework中表达呢? Is my configuration incorrect? 我的配置不正确吗?

Also interestingly, when I switch the above-mentioned query around to this dumb version to test things (with the one-to-one mapping still in place in EF): 同样有趣的是,当我将上述查询切换到该哑巴版本以测试事物时(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();

all of the provisional data comes back, but some of the Destinations do not . 所有的临时数据都会返回,但某些“目的地”则不会 This hints to me that it has something to do with including navigation properties multiple levels deep across a one-to-one. 这向我暗示,这与在一对一的深度内包含多个级别的导航属性有关。 Has anyone else experienced this behavior before? 有没有其他人经历过这种行为?

EF does not officially support 1:1 associations other than in shared primary key 1:1 association situations. EF在共享主键1:1关联情况下不正式支持1:1关联。

What you are doing is create 1:many's and trying to tell EF that it's really a 1:1. 您正在执行的操作是创建1:1:1,然后尝试告诉EF它实际上是1:1。 The problem is, the db schema is really a 1:many schema and EF will have problems here. 问题是,db模式实际上是一个1:many模式,EF在这里会出现问题。

If your requirement is 1:1, then you need to use a shared primary key (both entities have the same primary key), and one also treats it as a foreign key). 如果您的要求是1:1,则需要使用共享的主键(两个实体都具有相同的主键),并且也将其视为外键)。

I am facing the problems before, Mine solution was using 1:many because if POCOA include POCOB 我之前遇到的问题,我的解决方案使用的是1:many,因为如果POCOA包含POCOB

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

really return the POCOB as a list, since we know it 100% return one record, then during getting the data, we can say a.SingleOrDefault(); 真正将POCOB作为列表返回,因为我们知道它100%返回一条记录,因此在获取数据期间,我们可以说a.SingleOrDefault();。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM