【问题标题】:Entity Framework - Multiple Project support实体框架 - 多项目支持
【发布时间】:2009-12-18 21:40:03
【问题描述】:

我正在考虑将一个大型项目迁移到 Entity Framework 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,而一些用户将同时使用这两者。我只运送用户需要的组件。因此,Assembles 的行为有点像插件,因为它们向核心应用程序添加了功能。

实体框架中是否有支持这种情况的方法?

基于this SO question,我认为这样的事情可能会奏效:

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

但即使这样可行,但似乎我的 EDMX 文件需要了解所有项目。我希望每个项目都包含该项目中类的元数据,但我不确定这是否可能。

如果实体框架无法做到这一点,是否还有其他可行的解决方案(NHibernate、Active Record 等)?

【问题讨论】:

    标签: c# nhibernate entity-framework castle-activerecord


    【解决方案1】:

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

    ...但只有当您为每种不同类型的客户端应用程序都有专门的模型(即 EDMX)时,它才会起作用。

    这是因为 EF(和大多数其他 ORM)要求模型中的每个实体都有一个类,所以如果某些客户不知道某些类,您将需要一个没有相应实体的模型——即定制的 EDMX每个场景。

    为了更轻松地为每个客户端应用程序创建新模型,如果我是你,我会按照我博客上的 best practices 使用 Code-Only,以便轻松抓取您实际需要的模型。

    希望对你有帮助

    亚历克斯

    【讨论】:

    • 看起来只有代码是要走的路。 Code-Only 可以与 EDMX 模型结合使用吗?例如在我的主项目中有一个 EDMX(在我的例子中是 Person)然后在其他项目中只做代码?
    • Code-Only 背后的想法是没有 EDMX。当然,在后台会生成相同的信息,您可以使用挂在 ContextBuilder 上的 WriteEDMX() 方法将其转换为 EDMX 格式。所以我的建议是在任何地方都使用 Code-Only,包括你的主项目,并且只有在你需要可视化模型时才使用 WriteEDMX。
    【解决方案2】:

    Alex 是正确的 (+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,而不是任何类型的映射实体。

    这样,您就实现了拥有通用数据模型的目标,但在单独的项目中拥有“特定于工作类型”的元素。

    【讨论】:

    • 我正在考虑将 person 类更改为接口,因此它将是 PoliceOfficer : IPerson,它可能比继承更好,但在我的现实世界应用程序中,子对象都有一些共享行为,这通常与继承一起工作得更好。我将研究数据投影,但我的大多数子类没有重叠属性。我也不确定它如何与每个子类数据库的现有表一起工作。
    猜你喜欢
    • 2014-03-06
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    相关资源
    最近更新 更多