poco object Accessibility
I am using poco objects I wrote with entity framework.
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:public class P {
pub开发者_JAVA百科lic 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. These will then be serialized when transporting the poco's. If you use XmlSerializer
only the public properties will be serialized and you can exclude properties with [XmlIgnore]
attribute.
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. 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.
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.)
The public
access modifier marks a type and a member of a type as accessible from external libraries. 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).
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. 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
. 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).
private
members are used to contain members that should not be exposed outside of the parent type. E.g. a backing field for a property will almost always be private.
The general rule I follow is:
public
members expose specific functionality I want to be usable from external types/assemblies.protected
members expose specific functionality I want to be usable from inheriting types only.private
members hide functionality that I want to contain to just the parent type. E.g. I want a use a method which is specific to the type and has no benefi being exposed publicly. E.g. state mutation methods that I want to control from external access, etc.
Others:
internal
allows me to mark members as accessible within only the assembly that contains them. 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.- I rarely use
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). Changing accessibility will most probably break either tracking proxies, lazy loading or both as described in link provided by @dlev.
- Members don't have to be
virtual
. If you want lazy loading you must mark all mapped navigation propertiesvirtual
. If you want tracking proxies you must mark all other propertiesvirtual
.
Code first (only EFv4.1):
- In this case situation is worse. Members must be
public
. In special case when entity is in the same assembly as context or mapping configuration members can beinternal
(I skipInternalsVisibleTo
because it is not very nice scenario). In case when mapping configuration is nested class of entity, members can be alsoprivate
orprotected
but this strongly breaks whole meaning of POCO because POCO entity must contain EF dependent nested class. 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
keyword is needed because EF will create new type at runtime derived from entity type. This type is referred as proxy and it overrides behaviour in property getter and setter. In case of lazy loading it adds call to Load
operation which triggers loading of relation when accessed first time. In case of change tracking proxies it informs ObjectStateManager
/ DbChangeTracker
about each change to attached entity. 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.
精彩评论