简体   繁体   English

poco对象可访问性

[英]poco object Accessibility

I am using poco objects I wrote with entity framework. 我正在使用通过实体框架编写的poco对象。
I would like to know about the accessibility levels of the members that used as data fields (members that mapped to field in table from the database: 我想了解用作数据字段的成员(从数据库映射到表中字段的成员的可访问性级别:
For entity named P: 对于名为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;}
}

Does the members must be public? 成员必须公开吗?
Does the members must be virtual? 成员必须是虚拟的吗?
Does the members can be private? 成员可以私人吗?

What are the rules for the members accessibility? 成员可访问性的规则是什么?

Depends on the communication technology you are using. 取决于您使用的通信技术。 When using WCF (which uses DataContractSerializer ) you can set the accessibility to anything you prefer and put the [DataMember] attribute above any private, protected or public field or property. 使用WCF(使用DataContractSerializer )时,可以将访问权限设置为您喜欢的任何内容,并将[DataMember]属性放在任何私有,受保护或公共字段或属性之上。 These will then be serialized when transporting the poco's. 然后在运输poco时将这些序列化。 If you use XmlSerializer only the public properties will be serialized and you can exclude properties with [XmlIgnore] attribute. 如果使用XmlSerializer仅公共属性将被序列化,并且可以使用[XmlIgnore]属性排除属性。

About virtual: virtual has nothing to do with accessibility but more with OOP by giving derived classes the possibility to override the declared properties / methods. 关于虚拟:虚拟与可访问性无关,而与OOP无关,它通过为派生类提供重写声明的属性/方法的可能性。 This depends on the design that you need / prefer. 这取决于您需要/喜欢的设计。

So first think about the accessibility of the fields / properties that your classes need in combination with the serialization technique to be used. 因此,首先考虑一下您的类需要结合使用的序列化技术来访问字段/属性。

If you want to use POCO objects with Entity Framework so that they are auto-tracked, there are a number of requirements that have to be met, which are listed here . 如果要将POCO对象与Entity Framework一起使用,以便对其进行自动跟踪,则必须满足许多要求,这些要求在此处列出。

To your question specifically, properties must be declared as public and virtual if you want your class to support lazy loading (since the EF will derive a proxy class from your class and override the properties to provide the functionality.) 特别是对于您的问题,如果您希望您的类支持延迟加载,则必须将属性声明为publicvirtual (因为EF将从类中派生代理类并覆盖属性以提供功能)。

The public access modifier marks a type and a member of a type as accessible from external libraries. public访问修饰符将类型和类型的成员标记为可从外部库访问。 This means if you have a type in assembly A, and you add a reference to it from assembly B, it means you can access that type/member from types exposed in assembly B. There are other access modifiers (read up about them here ). 这意味着,如果程序集A中有一个类型,并且从程序集B中添加了对该类型的引用,则意味着您可以从程序集B中公开的类型访问该类型/成员。还有其他访问修饰符( 在此处进行阅读) 。

Knowing how access modifiers change the behaviour of types is an important part of object orientated design. 知道访问修饰符如何改变类型的行为是面向对象设计的重要部分。

virtual members allow a type to provide a default implementation of specific functionality. virtual成员允许一种类型提供特定功能的默认实现。 For example, if I had a type: 例如,如果我有一个类型:

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

I could have a type: 我可以有一个类型:

public class DebugLogger : Logger {

}

That type will expose my default implementation of Write as the method Logger.Write . 该类型将把我的默认Write实现公开为Logger.Write方法。 I could (optional) override this behaviour: 我可以(可选)覆盖此行为:

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

Using this use of virtual / override allows classes to optional customise their behaviour, and when Write is called with a reference simple to a Logger instance, the correct implementation will be called (so, the overriden method in the latter case). 使用virtual / override这种使用允许类可选地自定义其行为,并且当使用Logger实例的简单引用来调用Write时,将调用正确的实现(因此,在后一种情况下,重写方法)。

private members are used to contain members that should not be exposed outside of the parent type. private成员用于包含不应在父类型之外公开的成员。 Eg a backing field for a property will almost always be private. 例如,财产的背景几乎总是私有的。

The general rule I follow is: 我遵循的一般规则是:

  1. public members expose specific functionality I want to be usable from external types/assemblies. public成员公开了我希望可以从外部类型/程序集中使用的特定功能。
  2. protected members expose specific functionality I want to be usable from inheriting types only. protected成员公开特定的功能,我希望仅可用于继承类型。
  3. private members hide functionality that I want to contain to just the parent type. private成员将我想包含的功能隐藏到父类型中。 Eg I want a use a method which is specific to the type and has no benefi being exposed publicly. 例如,我想使用一种特定于该类型的方法,并且不会公开暴露任何受益人。 Eg state mutation methods that I want to control from external access, etc. 例如,我想从外部访问控制的状态突变方法等。

Others: 其他:

  1. internal allows me to mark members as accessible within only the assembly that contains them. internal使我可以将成员标记为只能在包含它们的程序集中访问。 This is useful when you need to expose things like builder methods, etc. which are specific to the containing assembly, that you don't want to mark as public but cannot be used as private members. 当您需要公开特定于包含程序集的诸如构建器方法之类的东西,而您不想将其标记为公共但不能用作私有成员时,这很有用。
  2. I rarely use protected internal . 我很少使用protected internal

Hope that helps! 希望有帮助!

This strongly depends on the approach you are using. 这在很大程度上取决于您使用的方法。

Model / Database first: 型号/数据库优先:

  • Members don't have to be public but it has some consequences. 成员不必公开,但这会带来一些后果。 POCO property getters and setters must have same accessibility as defined in EDMX (shown in linked answer). POCO属性获取器和设置器必须具有与EDMX中定义的相同的可访问性(在链接的答案中显示)。 Changing accessibility will most probably break either tracking proxies, lazy loading or both as described in link provided by @dlev. 如@dlev提供的链接所述,更改可访问性很可能会破坏跟踪代理,延迟加载或同时破坏两者。
  • Members don't have to be virtual . 成员不必是virtual If you want lazy loading you must mark all mapped navigation properties virtual . 如果要延迟加载,则必须将所有映射的导航属性标记为virtual If you want tracking proxies you must mark all other properties virtual . 如果要跟踪代理,则必须将所有其他属性标记为virtual

Code first (only EFv4.1): 代码优先(仅EFv4.1):

  • In this case situation is worse. 在这种情况下情况更糟。 Members must be public . 成员必须public In special case when entity is in the same assembly as context or mapping configuration members can be internal (I skip InternalsVisibleTo because it is not very nice scenario). 在特殊情况下,当实体与上下文位于同一程序集中或映射配置成员可以位于internal (我跳过InternalsVisibleTo因为这不是很好的情况)。 In case when mapping configuration is nested class of entity, members can be also private or protected but this strongly breaks whole meaning of POCO because POCO entity must contain EF dependent nested class. 如果映射配置是实体的嵌套类,则成员也可以是privateprotected但这会严重破坏POCO的全部含义,因为POCO实体必须包含EF依赖的嵌套类。 The whole point is that mapping is done in code and it is affected by accessibility rules. 重点是映射是用代码完成的,并且受可访问性规则的影响。
  • virtual keyword has same meaning as in Model and Database first approaches. virtual关键字的含义与“模型和数据库”优先方法中的含义相同。

virtual keyword is needed because EF will create new type at runtime derived from entity type. 由于EF会在运行时从实体类型派生新类型,因此需要virtual关键字。 This type is referred as proxy and it overrides behaviour in property getter and setter. 此类型称为代理,它覆盖属性getter和setter中的行为。 In case of lazy loading it adds call to Load operation which triggers loading of relation when accessed first time. 在延迟加载的情况下,它会向Load操作添加调用,该调用在首次访问时触发关系的加载。 In case of change tracking proxies it informs ObjectStateManager / DbChangeTracker about each change to attached entity. 如果发生更改跟踪代理,它将向ObjectStateManager / DbChangeTracker通知对附加实体的每次更改。 If tracking proxies are not used EF must use snapshot tracking which evaluates all changes to attached entity during saving which is considered as much slower operation. 如果不使用跟踪代理,则EF必须使用快照跟踪来评估保存过程中对连接实体的所有更改,这被认为操作速度较慢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM