poco对象可访问性

时间:2011-05-15 18:05:47

标签: c# .net entity-framework accessibility

我正在使用我用实体框架编写的poco对象 我想知道用作数据字段的成员的可访问性级别(从数据库映射到表中字段的成员:
对于名为P的实体:

public class P {
    public virtual long Id{get;set;}
    public virtual string Name{get;set;}
    public virtual long CompanyId{get;set;}
    public virtual Company Company{get;set;}
}

会员必须公开吗?
成员必须是虚拟的吗? 会员可以是私人的吗?

会员辅助功能的规则是什么?

4 个答案:

答案 0 :(得分:2)

取决于您正在使用的通信技术。使用WCF(使用DataContractSerializer)时,您可以将可访问性设置为您喜欢的任何内容,并将[DataMember]属性置于任何私有,受保护或公共字段或属性之上。这些将在运输poco时序列化。如果您使用XmlSerializer,则只会序列化公共属性,您可以排除具有[XmlIgnore]属性的属性。

关于虚拟:虚拟与可访问性无关,但通过为派生类提供覆盖声明的属性/方法的可能性,与OOP无关。这取决于您需要/喜欢的设计。

首先考虑一下您的类所需的字段/属性的可访问性以及要使用的序列化技术。

答案 1 :(得分:2)

如果您想将POCO对象与Entity Framework一起使用以便自动跟踪它们,则必须满足许多要求,这些要求列在here中。

具体来说,如果您希望您的类支持延迟加载,则必须将属性声明为publicvirtual(因为EF将从您的类派生代理类并将属性覆盖为提供功能。)

答案 2 :(得分:1)

public访问修饰符将类型和类型成员标记为可从外部库访问。这意味着如果您在程序集A中有一个类型,并且从程序集B添加对它的引用,则意味着您可以从程序集B中公开的类型访问该类型/成员。还有其他访问修饰符(阅读它们{{ 3}})。

了解访问修饰符如何改变类型的行为是面向对象设计的重要部分。

virtual成员允许类型提供特定功能的默认实现。例如,如果我有一个类型:

public class Logger {
    protected virtual void Write(string message) {
        Console.Write(message);
    }
}

我可以有一个类型:

public class DebugLogger : Logger {

}

该类型会将Write的默认实现公开为方法Logger.Write。我可以(可选)覆盖此行为:

public class DebugLogger : Logger {
    protected override void Write(string message) {
        Debug.Print(message);
    }
}

使用virtual / override的这种使用允许类可选地自定义它们的行为,并且当使用对Write实例的简单引用调用Logger时,正确将调用实现(因此,后一种情况下的overriden方法)。

private成员用于包含不应在父类型之外公开的成员。例如。一个属性的支持字段几乎总是私有的。

我遵循的一般规则是:

  1. public成员公开我想要从外部类型/程序集中使用的特定功能。
  2. protected成员公开我希望仅从继承类型中使用的特定功能。
  3. private成员将我想要包含的功能隐藏到父类型中。例如。我想要使​​用一种特定于该类型的方法,并且没有公开暴露的好处。例如。我希望通过外部访问等控制的状态变异方法
  4. 其他:

    1. internal允许我在仅包含它们的程序集中将成员标记为可访问。当您需要公开特定于包含程序集的构建器方法等内容时,这非常有用,您不希望将其标记为公共但不能用作私有成员。
    2. 我很少使用protected internal
    3. 希望有所帮助!

答案 3 :(得分:0)

这在很大程度上取决于您使用的方法。

模型/数据库优先:

  • Members don't have to be public但它有一些后果。 POCO属性getter和setter必须具有EDMX中定义的相同可访问性(以链接的答案显示)。更改可访问性很可能会破坏跟踪代理,延迟加载或两者兼有,如@dlev提供的链接所述。
  • 会员不一定是virtual。如果要延迟加载,则必须标记所有映射的导航属性virtual。如果您想要跟踪代理,则必须标记所有其他属性virtual

代码优先(仅限EFv4.1):

  • 在这种情况下情况更糟。成员必须是public。在特殊情况下,当实体与上下文或映射配置在同一个程序集中时,成员可以是internal(我跳过InternalsVisibleTo,因为它不是很好的情况)。如果映射配置是嵌套的实体类,则成员也可以是privateprotected,但这会严重破坏POCO的全部含义,因为POCO实体必须包含EF依赖的嵌套类。重点是映射是在代码中完成的,它受可访问性规则的影响。
  • virtual关键字与模型和数据库第一种方法具有相同的含义。
需要

virtual关键字,因为EF将在运行时从实体类型派生新类型。此类型称为代理,它会覆盖属性getter和setter中的行为。在延迟加载的情况下,它会添加对Load操作的调用,这会在第一次访问时触发加载关系。如果更改跟踪代理,它会通知ObjectStateManager / DbChangeTracker每个对附加实体的更改。如果未使用跟踪代理,则EF必须使用快照跟踪,该跟踪会在保存期间评估对附加实体的所有更改,这被视为操作速度较慢。