【问题标题】:POCO objects Inheritance or Abstract?POCO 对象继承还是抽象?
【发布时间】:2012-12-09 23:13:25
【问题描述】:

我只是想在 POCO 中模拟一个数据模型。但我对一些事情有点困惑。让我们假设这个例子我将使用实体框架来实现 ORM。首先我有一个电话和地址类:

public class Phone
{
    int Id { get; set; }
    int Number { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public string Street { get; set; }
    public string Suite { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public int Zip { get; set; }
}

接下来我有一个 Person 和一个 Company 类:

public class Person
{
    int Id { get; set; }
    string FirstName { get; set; }
    string MiddleName { get; set; }
    string LastName { get; set; }
    string Prefix { get; set; }
}

public class Company
{
    int Id { get; set; }
    int Name { get; set; }
}

假设我希望 Person 和 company 都拥有电话或地址列表,逻辑上我可能会从代码的角度考虑创建一个抽象类 AContact:

public abstract class AContact
{
    ICollection<Phone> Phone { get; set; }
    ICollection<Address> Address { get; set; }
}

然后让我的公司和个人继承这个:

public class Company : AContact
{
    int Id { get; set; }
    int Name { get; set; }
}

public class Person : AContact
{
    int Id { get; set; }
    string FirstName { get; set; }
    string MiddleName { get; set; }
    string LastName { get; set; }
    string Prefix { get; set; }
}

或者我可以创建一个接口:

public interface IContact
{
    ICollection<Phone> Phone { get; set; }
    ICollection<Address> Address { get; set; }
}

并实现接口:

public class Company : IContact
{
    public int Id { get; set; }
    public int Name { get; set; }
    public ICollection<Phone> Phone { get; set;}
    public ICollection<Address> Address {get; set;}
}

现在我明白了抽象类和接口之间的区别。但是这应该如何实现实体框架的功能呢?从网上的一些搜索看来,从 4.1 开始,你不能做接口的事情,这是否意味着我必须使用抽象类?或者我是否只需要在我想使用它们的每个类中明确定义这两个属性?还有像 RavenDB 这样的东西在那里也能工作吗?

【问题讨论】:

    标签: entity-framework interface abstract-class poco


    【解决方案1】:

    这两种选择都可以。

    使用您的界面时,您的 DbContext 将如下所示:

    public class MyContext : DbContext
    {
        public IDbSet<Company> Companies { get; set; }
        public IDbSet<Person> People { get; set; }
    }
    

    您将获得也恰好实现了您指定的接口的 Companies 和 People 对象。

    使用抽象类时,您将拥有以下内容:

    public class MyContext : DbContext
    {
        public IDbSet<AContact> Contacts { get; set; }
    }
    

    使用抽象基类,您将拥有一个实体集。使用OfType&lt;T&gt;,您可以将集合过滤到特定时间。

    RavenDB 是一个完全不同的主题。这是一个运行非常流畅的 NoSql 数据库。它将您的对象序列化为 JSON 并为您存储它们。你可以使用(几乎)你想要的每一个类结构。

    【讨论】:

    • EF 将其转换为实际数据库的方式有何不同?我倾向于尝试使用 RavenDB 来消除“翻译”。但我很好奇这是否是 EF 项目的合理解决方案。我这样做的原因是因为我有一个基本实现,它将被其他代表“联系人”的项目使用,但“个人”和“公司”仅适用于各自的实现。两个不同的项目,它们使用相同的模型和一个基本的抽象上下文类,但具有不同的上下文实现以及它们自己的属性。有意义吗?
    • 第一个选项将被翻译成一个有两个完全独立的表的数据库。第二个需要一些映射。映射继承时,您有三个选项:每个类型的表、每个层次结构的表、每个具体类型的表(请参阅weblogs.asp.net/manavi/archive/2010/12/24/…
    • 所以我最初尝试使用抽象类,它实际上工作得很好。但是我在尝试序列化为 JSON 时遇到了一些问题。显然 Json.NET 要求您在继承自抽象类的 POCO 类上实现 CustomCreationConverter。所以我会有一个 CompanyConverter 和一个 PersonConverter 当您尝试调用 JsonConvert.DeserializeObjectAsyn 时,问题就来了,因为您必须将该方法传递给反序列化,但直到您反序列化它之后才能确切知道它是什么类型的对象,所以我不能知道要传递哪种转换器方法。
    • 另外,在为抽象类方法实现存储库模式时。为每个(个人和公司)创建一个存储库还是为两者(AContact)创建一个存储库会更好。我有一种感觉,这将在以后导致很多复杂性。但是我有合理的需要将它们分开,因为会有两个站点;一种是 Company 有意义,另一种是 Person 更合适,而且根本不会使用 company。我不介意在必要时将它们组合起来,但这实际上只是目前更多的理解练习。
    • 如果你在哪里,我会用一些示例代码问一个关于 Json.NET 问题的新问题。我敢打赌,你会得到更多的答案。关于存储库问题,我建议您使用 Google 搜索“聚合根”。存储库在领域驱动设计中被广泛使用。 DDD 提供有关您应该创建哪些存储库的建议。就个人而言,我会创建两个独立的存储库,因为 Company 和 Person 是两个不同的实体,它们都与其他实体有自己的关系。
    猜你喜欢
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 2011-04-22
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多