2009-12-18 105 views
2

我正在研究將大型項目遷移到實體框架4.0,但不知道它是否可以處理我的繼承場景。實體框架 - 多項目支持

我有幾個項目從「主」項目中的對象繼承。下面是一個簡單的基類:

namespace People 
{ 
    public class Person 
    { 
     public int age { get; set; } 
     public String firstName { get; set; } 
     public String lastName { get; set; } 

    } 
} 

和子類中的一個:

namespace People.LawEnforcement 
{ 
    public class PoliceOfficer : People.Person 
    { 
     public string badgeNumber { get; set; } 
     public string precinct { get; set; } 
    } 
} 

而這正是該項目的佈局看起來像:

People - People.Education - People.LawEnforcement http://img51.imageshack.us/img51/7293/efdemo.png

一些客戶的應用程序將使用People.LawEnforcement中的類,其他用戶將使用People.Education,並且一些將使用兩者。我只運送用戶需要的組件。所以彙編有點像插件,它們爲核心應用增加了特性。

在Entity Framework中是否有支持這種情況的方法?

基於this SO question我覺得這樣的事情可能工作:

ctx.MetadataWorkspace.LoadFromAssembly(typeof(PoliceOfficer).Assembly); 

但是,即使是工作那麼它的接縫,彷彿我的EDMX文件將需要了解的所有項目。我寧願讓每個項目都包含該項目中類的元數據,但我不確定這是否可行。

如果這是不可能的實體框架是否有另一種解決方案(NHibernate的,活動記錄等),將工作?

回答

5

是的,這是可能的,使用您已經找到的LoadFromAssembly(..)方法。

...但只有當您針對每種不同類型的客戶端應用程序都有專門的模型(即EDMX)時才能正常工作。

這是因爲EF(和大多數其他ORM)需要模型中每個實體的類,所以如果某些客戶端不知道某些類,則需要一個沒有相應實體的模型 - 即定製EDMX爲每個場景。

爲了更容易地爲每一個客戶端應用的新模式,如果我是你,我會用Code-Only下在我的博客中規定的​​best practices,使之容易搶只有你所需要的模型的片段實際上需要。

希望這有助於

亞歷

+0

它看起來像Code-Only就是要走的路。只能將代碼與EDMX模型結合使用?例如在我的主項目中有一個EDMX(在我的例子中是Person),然後在其他項目中執行代碼? – TonyB 2009-12-18 16:30:50

+0

那麼Code-Only背後的想法就是沒有EDMX。當然,在引擎蓋下,會生成相同的信息,您可以使用WriteEDMX()方法掛起ContextBuilder將其轉換爲EDMX格式。因此,我的建議是在任何地方使用Code-Only,包括您的主項目,並且只有在需要可視化模型時才使用WriteEDMX。 – 2009-12-18 20:43:46

5

亞歷克斯是正確的(+1),但我強烈建議你重新考慮你的模型。在現實世界中,警察不是一個人的子類型。相反,這是該人員就業的一個屬性。我認爲程序員經常傾向於過分強調繼承,但是犧牲了面向對象設計的組合性,但是在O/R映射中尤其存在問題。請記住,對象實例只能有一種類型。將該對象存儲在數據庫中時,實例只能存在多個應用程序會話中的該類型。如果一個人有兩份工作,例如警察和老師,會怎麼樣?也許這種情況不太可能,但總體問題比你想象的要普遍。

與您的問題更相關,我認爲您可以通過使您的映射實體模型更加通用,以及針對實體的應用程序特定數據預測而不是實體本身來解決您的實際問題。考慮像實體:

public class JobType 
{ 
    public Guid Id { get; set; } 
    // ... 
} 

public class Job 
{ 
    public JobType JobType { get; set; } 
    public string EmployeeNumber { get; set; } 
} 

public class Person 
{ 
    public EntityCollection<Job> Jobs { get; set; } 
} 

現在你的執法程序可以這樣做:

var po = from p in Context.People 
     let poJob = p.Jobs.Where(j => j.JobType == JobType.PoliceOfficerId).FirstOrDefault() 
     where poJob != null 
     select new PoliceOfficer 
     { 
      Id = p.Id, 
      BadgeNumber = poJob.EmployeeNumber 
     }; 

哪裏PoliceOfficer只是一個POCO,沒有映射任何形式的實體。

因此,您已經實現了擁有通用數據模型但在單獨項目中具有「作業類型特定」元素的目標。

+0

我正在考慮將人員類改爲接口,所以它將成爲PoliceOfficer:IPerson它可能比繼承更好,但在我的真實世界的應用程序中,子對象都有一些共享行爲,這通常可以更好地繼承。 我會研究數據預測,但我的大多數子類沒有重疊的屬性。我也不確定這種工作是如何與每個子類數據庫的現有表一起工作的。 – TonyB 2009-12-18 16:16:35