2013-08-01 22 views
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; } 
} 

從地塊到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(); 

所有的臨時數據會返回,但某些目的地不會。這向我暗示,它與包含跨越一對一深層的導航屬性有關。其他人有沒有經歷過這種行爲?

回答

0

EF不正式支持1:1關聯,而不是在共享主鍵1:1關聯情況下。

你在做什麼是創建1:many's,試圖告訴EF它確實是1:1。問題是,數據庫模式實際上是1:多模式,EF在這裏會遇到問題。

如果您的要求是1:1,那麼您需要使用共享主鍵(兩個實體具有相同的主鍵),另一個也將其視爲外鍵)。

+0

我應該注意到數據庫在我們的模型中首先出現,並且SQL Server在添加適當的約束(我們有)時將該關係識別爲一對一。這似乎是使用共享主鍵的合理替代方法(無論它是否是SQL世界中的標準/被接受​​的方法,我想我不知道 - 這更像是一個DBA問題,但最初我們是這麼做的) 。你知道這是EF團隊有意識的設計決定嗎? – jgoeglein

+0

@jgoeglein - EF不支持任何形式的約束,所以這就是爲什麼它需要共享主鍵。這是保證模型執行的唯一方式(不受限制)。所以是的,這是一個有意識的決定,因爲缺乏對約束的支持。是的,這是合理的,但不受支持。您可以通過使用存儲的proc來備份模型,從而在EF6中脫身。但是,EF6仍處於測試階段,可能直到秋季纔會發佈。雖然,第二個想法,我想我不知道外匯基金將如何加入sproc背景加入.. –

+0

只是在這一點上,事實證明,你不**有**使用共享主鍵如果你不關心雙向關係 - 你可以在一對多的情況下建立一個單向關聯,而不需要配置多邊來給出約束的錯覺:[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

0

我之前所面臨的問題,礦溶液用1:很多,因爲如果POCOA包括POCOB

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

真時返回POCOB作爲一個列表,因爲我們知道它100%的回報率的一個記錄,然後獲取數據,我們可以說a.SingleOrDefault();

相關問題