【问题标题】:EF Code First - How to Model This?EF Code First - 如何对此建模?
【发布时间】:2012-04-05 23:19:34
【问题描述】:

我正在开发一个使用实体框架代码的网络应用程序 (MVC),并且我正在尝试弄清楚如何对此进行建模。我当然可以向一个类(数据库中的位)添加 15 个布尔值,但这似乎是一种可悲的方式。我目前有一个客户对象,其中包含下图所示策略的对象。

我希望我的视图看起来像上面的一样,目前没有计划添加 6th,但构建模型以支持这种可能性很重要。

public class customer{
   //some random properties like Id, Name, Owner, Etc.
   //I could put 15 bools here for the policies in the image
   //I could put a policy object here?
}

【问题讨论】:

  • 你的班级模型现在是什么样子的?具体来说,“Original Medicare”是与“TriCare for Life”不同的类别,还是同一类别的两个实例?
  • 我刚刚更新了帖子......基本上客户对象是所有这些数据的主人。每个客户都有一份医疗保险政策,其中包含对这些问题的答案(答案是是/否或布尔值)......
  • 装饰器模式将成为您的朋友,其中包含类型的枚举和值的位掩码。我带着手机在山里,所以很遗憾,直到稍后在这里才能详细说明:)

标签: c# asp.net-mvc asp.net-mvc-3 entity-framework ef-code-first


【解决方案1】:

这是一个简单、自我描述、可扩展、规范化和可扩展的设计。您可以添加其他策略类型或患者类型,而无需重新编译系统。您没有说明您使用的是哪个数据库引擎,因此为了使其能够在大多数数据库平台上运行,我建议您使用TPC

患者只是一个人(又名当事人)在系统中扮演的角色。您可以拥有其他角色,例如“医生”、“员工”、“保单持有人”等,每个角色都有自己的数据。重要的是要注意角色是临时性的,这意味着可以取消单个角色,而该人在系统中执行其他角色。

如果“Existing”、“AgeIn”、“NewPatient”可以通过查看 Role 或 Party 的属性来确定,则不需要 PatientType。我添加它是因为尚不清楚耐心的类型是如何定义的。您很可能只需在 Patient 上有一个属性来定义它。

一方代表任何法律实体。各方之间的关系通常对企业很重要。因此,当“山姆”(一个人)来到“医生”(一个扮演角色的人)时,重要的是要知道她父亲鲍勃(一个人)的“政策”将支付账单。因此,一个人被映射到不同的表中的原因。

PolicyType 定义策略的真正类型。在您的情况下,您可能有 18 种不同的保单类型,例如 ExistingOriginalMediCare、AgeInOriginalMediCare 等。您可以在此处存储影响策略“规则”的数据。例如,某些类型的政策仅适用于居住在加利福尼亚州的人。我工作的一个系统有数千种策略类型,每种策略类型都有数百个应用程序用来推断业务规则的属性。这允许企业创建新的策略类型和“规则”,而无需重新编译系统和依赖它的所有内容。

但是,可以通过在保持相同功能的同时取出继承来简化它。这里我们假设除了“患者”之外没有其他“角色”,除了“人”之外没有其他“当事人”。

也就是说,这实际上取决于数据是否会被其他应用程序重用,以及时间数据和关联的真实情况如何。随意适应。我在设计系统时经常参考这些书:

  1. Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML
  2. Enterprise Model Patterns: Describing the World (UML Version)
  3. The Data Model Resource Book, Volume 3: Universal Patterns for Data Modeling

它们从根本上改变了我看待“数据”的方式。

【讨论】:

  • 感谢您的长回答。我知道这需要很多思考和时间。在这种情况下,客户实际上并不是患者。客户是我们跟踪政策的 B2B 合作伙伴。换句话说,提供者有医疗保险政策,我们想知道这些政策是什么。我会进一步研究一下。数据库是 SQL 服务器。
  • 那么最好将“Patient”重命名为“Partner”,将“Person”重命名为“Organization”。模式保持不变。您是否必须跟踪政策的受益人?
  • 没有受益人/患者参与。纯B2B。我不得不把这个问题拼凑起来,以保护一些导致混乱的东西......
【解决方案2】:

您可以查看 TPT(每种类型的表格),查看此处http://blogs.microsoft.co.il/blogs/gilf/archive/2010/01/22/table-per-type-inheritance-in-entity-framework.aspx

这意味着您可以为这些不同概念中的每一个提供一个表,这些概念扩展了一个基表。这样做的好处是稍后您可以将其他信息添加到特定类型。

例如,客户将是您的根表,然后使用 OriginalMedicareCustomer 等概念进行扩展

【讨论】:

  • 根据您的模型,TPT 在外键和级联删除方面可能是一个挑战。
  • 是的,它确实比常规表结构更难做,但在最新版本的 EF 中变得容易得多
【解决方案3】:

如果你想对其进行标准化,我建议你这样做:

public class Customer {
  // id, name, owner, etc
  public virtual IList<CustomerPolicy> Policies { get; set; }
}

public class CustomerPolicy {
  // id, name, etc
  public bool ExistingPatient { get; set; }
  public bool AgeInPatient { get; set; }
  public bool NewPatient { get; set; }
}

如果不了解您的应用程序的更多信息,我不能说,但我猜每个策略的三个布尔值是互斥的?如果是这样,我会改为这样做:

public enum PatientType { Existing, AgeIn, NewPatient };

public class CustomerPolicy {
  // id, name, etc
  public PatientType PatientType { get; set; }
}

【讨论】:

    【解决方案4】:

    我不完全确定您的数据要求,但我会保持简单,在一两个表内,类似这样...

    public class Customer
    {
        public int CustomerID { get; set; }
        // or implement it via enum like below for policy type
        public bool Existing { get; set; }
        public bool AgeIn { get; set; }
        public bool New{ get; set; }
        // no 'virtual' means it's 'required', with virtual could be 'null'
        public Policy Policy { get; set; }
    }
    public enum PolicyBits
    {
        None = 0x00,
        ExistingOriginalMediCare = 0x01,
        // ...
        AgeInOriginalMediCare = 0x100,
        // ...
    }
    public class Policy
    {
        public int PolicyID { get; set; }
        public int PolicyTypeValue { get; set; }
        [NotMapped]
        public PolicyBits PolicyType
        {
            get { return (PolicyBits)PolicyTypeValue; }
            set { PolicyTypeValue = (int)value; }
        }
    }
    

    ...枚举将帮助您缩减“位”的数量 - 但它尚未得到官方支持,将来自下一个版本,到目前为止仅在实验性 VS 2011 和 .NET 4.5 中(我记得)。

    但您可以暂时使用以下方法解决它。

    至于表格的模型——我不确定你想如何在现有用户、新用户或老用户之间“切换”——或者你是否可以同时拥有这三个或所有三个等等。因为所有是位我认为一个字段应该就足够了 - 并且可能将它放在一个单独的表中进行分离 - 即你可以重新定义它,添加新事物或引入新记录等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多