我有一個(做作和過於簡單化,由於合同約束)的數據模型看起來應該像這樣的:一比一的關係不加載所有實體
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; }
}
從地塊到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手。這些批次中有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; }
}
和新地塊的配置是這樣的:
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);
}
}
一切工作完美無瑕。這裏唯一的缺點是這並不能反映數據庫中的真實約束,因此您可以在技術上嘗試將多個批次添加到相同的臨時數據片段,這在嘗試保存時會中斷。我可以建立邏輯來防止這種情況,但爲什麼我不能在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();
所有的臨時數據會返回,但某些目的地不會。這向我暗示,它與包含跨越一對一深層的導航屬性有關。其他人有沒有經歷過這種行爲?
我應該注意到數據庫在我們的模型中首先出現,並且SQL Server在添加適當的約束(我們有)時將該關係識別爲一對一。這似乎是使用共享主鍵的合理替代方法(無論它是否是SQL世界中的標準/被接受的方法,我想我不知道 - 這更像是一個DBA問題,但最初我們是這麼做的) 。你知道這是EF團隊有意識的設計決定嗎? – jgoeglein
@jgoeglein - EF不支持任何形式的約束,所以這就是爲什麼它需要共享主鍵。這是保證模型執行的唯一方式(不受限制)。所以是的,這是一個有意識的決定,因爲缺乏對約束的支持。是的,這是合理的,但不受支持。您可以通過使用存儲的proc來備份模型,從而在EF6中脫身。但是,EF6仍處於測試階段,可能直到秋季纔會發佈。雖然,第二個想法,我想我不知道外匯基金將如何加入sproc背景加入.. –
只是在這一點上,事實證明,你不**有**使用共享主鍵如果你不關心雙向關係 - 你可以在一對多的情況下建立一個單向關聯,而不需要配置多邊來給出約束的錯覺:[link](http://weblogs.asp .net/manavi/archive/2011/05/01/associations-in-ef-4-1-code-first-part-5-one-to-one-foreign-key-associations.aspx) – jgoeglein