代码之家  ›  专栏  ›  技术社区  ›  nathanchere Jitendra Vyas

我如何最好地解决这个对象类型的继承?某种枚举层次结构?

  •  2
  • nathanchere Jitendra Vyas  · 技术社区  · 15 年前

    我很好奇有什么解决方案可以用ORM方法(在本例中,使用实体框架4)处理对象层次结构。我正在研究EF4上的一些文档,并试图将其应用到一个简单的库存跟踪程序中。存货的可能类型如下:

    库存项目类型:

    • 硬件
      • 个人计算机
        • 桌面
        • 服务器
        • 笔记本电脑
      • 附件
        • 输入(键盘、扫描仪等)
        • 输出(监视器、打印机等)
        • 存储(U盘、磁带机等)
        • 通信(网卡、路由器等)
    • 软件

    在这种情况下,对于处理枚举有什么建议?枚举是偶数吗?我真的不想为这样一个相对简单的实验(如清单类型、清单子类型、清单类型到子类型等的表)建立一个荒谬的标准化数据库。我真的不想让我的数据模型过于复杂,因为每个子类型都是继承的,即使不包括其他属性或方法(除了PC类型,理想情况下,PC类型会有相关的附件和软件,但这可能超出了这里的范围)。

    感觉应该有一个真正简单,优雅的解决方案,但我不能把我的手指放在上面。感谢任何帮助或意见!

    4 回复  |  直到 10 年前
        1
  •  1
  •   Sunny    15 年前

    我认为这需要一个复合设计模式: http://www.dofactory.com/Patterns/PatternComposite.aspx

    代码如下:

    class InventoryItem
    {
        public string Name { get; private set; }
        public InventoryItem Parent { get; private set; }
        public IList<InventoryItem> Children { get; private set; }
    }
    

    嗯。

        2
  •  1
  •   ctorx    15 年前

    您可以使用类型层次结构…

    public interface IInventoryType
    {
        string Name { get; }
    }
    
    public class Hardware : IInventoryType
    {
        public string Name { get { return "Hardware"; } }
    
        public class PC : IInventoryType
        {
            public string Name { get { return "PC"; } }
    
            public class Desktop : IInventoryType
            {
                public string Name { get { return "Desktop"; } }
            }
    
            public class Server : IInventoryType
            {
                public string Name { get { return "Server"; } }
            }
        }
    }
    

    然后和他们合作可能看起来像这样…

    IInventoryType invType = new Hardware.PC.Server();
    
    if (invType is Hardware.PC.Server)
    {
         Console.WriteLine("Yes!");
    }
    else
    {
         Console.WriteLine("No!");
    }
    

    虽然它会起作用,但我不确定它是否有意义。这很容易变得复杂和难以维护。

    这可能更适合作为数据存储在数据库中,并编写代码以通用方式处理数据,而不是特定方式。

    每次添加新类型时,都需要更改代码,这并不理想。

        3
  •  1
  •   Aaronaught    15 年前

    这很难“荒谬地规范化”——事实上,一个自引用表就足以使用邻接列表模型将信息保存在数据库中:

    Categories (CategoryID, CategoryName, ParentCategoryID)
    

    在哪里? ParentCategoryID 参考文献 CategoryID 在同一张桌子上。

    这可以映射到一个非常简单的实体类:

    public class Category
    {
        public string Name { get; set; }
        public Category ParentCategory { get; set; }
        public IList<Category> ChildCategories { get; set; }
    }
    

    这就是你要做的一切。如果您开始有非常深/宽的层次结构,那么您可能需要考虑性能的替代模型,但是在这里给出的示例中,您离扩展简单邻接列表还有很长的路要走。

    忘了枚举-这里没有意义。如果这是一个数据驱动的应用程序,那么您几乎肯定希望能够在不更改代码的情况下更改类别列表,而枚举类型将要求您这样做。

        4
  •  1
  •   Doc Brown    15 年前

    您的问题的要点与ORM无关,它只是一个如何为您的需求建立一个好的关系模型的问题。您已经给出了答案:如果您不想为每个枚举建模不同的表,那么就不要这样做。对您的PC类型、附件类型等使用整数属性,并将其映射到代码中定义的枚举。这样,每当扩展一个枚举时,就不必更改数据库中的任何内容(甚至不必更改任何枚举表中的数据)。

    当然,在某些情况下,将枚举建模为单独的表是值得的。显然,当您必须将额外的数据存储到枚举中(如短名称、长名称、ID等)时,就是这种情况。或者当您有不同的程序时,可能是使用不同的编程语言,它们都需要处理相同的枚举集。或者,当用户不需要程序的新版本就可以扩展PC类型列表时。

    推荐文章