我正在使用我用实体框架编写的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;}
}
会员必须公开吗?
成员必须是虚拟的吗?
会员可以是私人的吗?
会员辅助功能的规则是什么?
答案 0 :(得分:2)
取决于您正在使用的通信技术。使用WCF(使用DataContractSerializer
)时,您可以将可访问性设置为您喜欢的任何内容,并将[DataMember]
属性置于任何私有,受保护或公共字段或属性之上。这些将在运输poco时序列化。如果您使用XmlSerializer
,则只会序列化公共属性,您可以排除具有[XmlIgnore]
属性的属性。
关于虚拟:虚拟与可访问性无关,但通过为派生类提供覆盖声明的属性/方法的可能性,与OOP无关。这取决于您需要/喜欢的设计。
首先考虑一下您的类所需的字段/属性的可访问性以及要使用的序列化技术。
答案 1 :(得分:2)
如果您想将POCO对象与Entity Framework一起使用以便自动跟踪它们,则必须满足许多要求,这些要求列在here中。
具体来说,如果您希望您的类支持延迟加载,则必须将属性声明为public
和virtual
(因为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
成员用于包含不应在父类型之外公开的成员。例如。一个属性的支持字段几乎总是私有的。
我遵循的一般规则是:
public
成员公开我想要从外部类型/程序集中使用的特定功能。protected
成员公开我希望仅从继承类型中使用的特定功能。private
成员将我想要包含的功能隐藏到父类型中。例如。我想要使用一种特定于该类型的方法,并且没有公开暴露的好处。例如。我希望通过外部访问等控制的状态变异方法其他:
internal
允许我在仅包含它们的程序集中将成员标记为可访问。当您需要公开特定于包含程序集的构建器方法等内容时,这非常有用,您不希望将其标记为公共但不能用作私有成员。protected internal
。希望有所帮助!
答案 3 :(得分:0)
这在很大程度上取决于您使用的方法。
virtual
。如果要延迟加载,则必须标记所有映射的导航属性virtual
。如果您想要跟踪代理,则必须标记所有其他属性virtual
。 public
。在特殊情况下,当实体与上下文或映射配置在同一个程序集中时,成员可以是internal
(我跳过InternalsVisibleTo
,因为它不是很好的情况)。如果映射配置是嵌套的实体类,则成员也可以是private
或protected
,但这会严重破坏POCO的全部含义,因为POCO实体必须包含EF依赖的嵌套类。重点是映射是在代码中完成的,它受可访问性规则的影响。virtual
关键字与模型和数据库第一种方法具有相同的含义。 virtual
关键字,因为EF将在运行时从实体类型派生新类型。此类型称为代理,它会覆盖属性getter和setter中的行为。在延迟加载的情况下,它会添加对Load
操作的调用,这会在第一次访问时触发加载关系。如果更改跟踪代理,它会通知ObjectStateManager
/ DbChangeTracker
每个对附加实体的更改。如果未使用跟踪代理,则EF必须使用快照跟踪,该跟踪会在保存期间评估对附加实体的所有更改,这被视为操作速度较慢。