2009-12-18 139 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