2014-03-26 74 views
1

我有兩個表,一個是自引用這樣的:有沒有辦法自定義實體查詢的默認行爲?

Job (id, description) 
JobAssembly (id, jobid, parentassemblyid) 

我也以同樣的方式有兩個域對象:

public class Job 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 

    public virtual List<JobAssembly> Assemblies { get; set; } 
} 

public class JobAssembly 
{ 
    public int Id { get; set; } 

    public int JobId { get; set; } 
    public virtual Job { get; set; } 

    public int? ParentAssemblyId { get; set; } 
    public virtual JobAssembly ParentAssembly { get; set; } 

    public virtual List<JobAssembly> SubAssemblies { get; set; } 
} 

這是問題所在。當我使用EF時:

using (var db = new JobContext()) 
{ 
    var job = db.Jobs.Find(1); 
} 

我按預期得到所要求的工作。但它帶有所有的裝配 - 不僅僅是父母,還有子裝配。這也是預料之中的。

我的問題是:我如何指示EF只帶入沒有子裝配的JobAssemblies ...作爲默認行爲?我知道如何查詢EF的父級程序集。但有沒有辦法設置映射,或者其他方式,將默認查詢行爲設置爲僅獲取其parentassemblyid == null的程序集?

謝謝:)

編輯:

讓我來說明一下:

我有ID的工作= 1,它有一個裝配有ID = 1組件1有兩個子組件分別是ids = 2和3。當執行var job = db.Jobs.Find(1)時,EF像這樣填充對象圖:

作業具有全部三個程序集(因爲jobid在所有三個== 1上)。具有ID 1的JobAssembly使其子部件適當地填充。

所有這些都是預期的,但如果我可以定製EF如何加載對象,那將會很好。作業不應該具有JobId == 1的每個JobAssembly,但只有JobId == 1和ParentAssemblyId == null的地方。

+0

你能顯示代碼?沒有'虛擬'關鍵字,因此不會延遲加載。所以你必須急於加載它,否則你不會得到任何程序集所有的程序集 – Colin

+0

我的錯。讓我顯示虛擬關鍵字。我將編輯。 –

+0

你想引入「只是父母」 - 即樹的根。或者你想引入「JobAssemblies沒有子裝配」 - 即葉子? – Colin

回答

2

如果我理解正確,您希望Job.Assemblies僅包含那些沒有父項的組件(即那些作業是直接子項的組件,而不是孫子項等)。

做到這一點的「正常」方式是隻讓直接孩子通過外鍵參考工作,讓孫子們等參考他們的父母。

爲了優化數據讀取(即您只需要在JobId上查詢一次,然後可以在內存中創建樹結構),我似乎很可能已經創建了Assemblies表。我會假設情況是這樣,而不是告訴你改變你的數據庫結構。如果情況並非如此,請告訴我。

有幾種方法可以讓你獲得工作的直接子女。最簡單的方法是隻有你的工作類的屬性做過濾爲您提供: -

public class Job 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 

    public virtual List<JobAssembly> Assemblies { get; set; } 

    public IEnumerable<JobAssembly> DirectChildren 
    { 
    get 
    { 
     return this.Assemblies == null 
     ? null 
     : this.Assemblies.Where(x => x.ParentAssemblyId == null); 
    } 
    } 
} 

,但如果你要採取這種方法你需要really really careful that you're not lazy loading data in a silly way。有些人在遇到問題時會想「我知道,我會用O/RM」。現在他們有N + 1個問題;)

更強大的解決方案是使用單獨的ViewModel來封裝您的應用程序層所需的樹結構。這可以防止選擇N + 1的問題,因爲你的數據層需要拉在一個查詢組件的整個列表的責任,然後將它們映射到你的應用程序層中的樹: -

public class JobViewModel 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 

    public virtual List<JobAssemblyViewModel> Children { get; set; } 
} 

public class JobAssemblyViewModel 
{ 
    public int Id { get; set; } 

    public virtual List<JobAssemblyViewModel> Children { get; set; } 
} 

如果你這樣做了很多,你可能要考慮使用例如AutoMapper將您的查詢投影到您的視圖模型上。

0

下面是使用繼承RootAssemblies和組件之間進行區分的想法:在這裏你填充`Assemblies`財產

public abstract class JobAssembly 
{ 
    public int Id { get; set; } 

    public virtual List<SubAssembly> SubAssemblies { get; set; } 
} 

public class SubAssembly : JobAssembly 
{ 
    public int ParentAssemblyId { get; set; } 

    public virtual JobAssembly ParentAssembly { get; set; } 
} 

public class RootAssembly : JobAssembly 
{ 
    public int JobId { get; set; } 

    public virtual Job Job { get; set; } 
} 

public class Job 
{ 
    public int Id { get; set; } 

    public string Description { get; set; } 

    public virtual List<RootAssembly> Assemblies { get; set; } 
} 
相關問題