Entity Classes & Architecture Patterns
Part of the Entity Framework FAQ .
2. Architecture and Patterns
2.1. Does Entity Framework have support for entity objects being responsible to save changes themselves (rather than a central Save method on object context)?
This is something we considered but in the end rejected in favor of the broader "unit of work" pattern where you can make changes to a series of related objects and then save them all at once. This is particularly useful when you are modifying relationships between entities or making changes to multiple entities that you want in a single transaction. You could do manually transaction management either way, but the default transactions that the entity framework supplies cover a large number of scenarios. You could, of course, with some work maintain a reference from your entities back to the objectcontext they go with and add a Save method to the entities, but it would still save all the outstanding changes on the context so that would probably be confusing/error prone. So this is an area were we don't directly support, but arguments can be made for either approach.
2.2. Does Entity Framework have support for "Persistence Ignorance"? What is Persistence Ignorance? What is POCO? IPOCO?
· Persistence ignorance is the general term for how much knowledge the objects must have of the persistence layer. In this case we talk primarily about “complete persistence ignorance” which is a step further than POCO in the sense that you’d like to be able to say that you can create an assembly of domain objects where that assembly doesn’t have any reference to a persistence stack at all, and then just by adding a small amount of code/configuration on the outside you can persist those objects.
· POCO is basically the idea of having plain CLR objects which do not have special requirements in order to work with a persistence stack like the EF. In practice this primarily talks about not requiring that the objects inherit from a particular base class and that they not be required to implement a particular interface. In many systems, though, you might say that they support POCO but still require something like attributes on the classes or other things in order to help convey some information to the persistence stack. The point, though, is that the domain objects don’t have to change substantively to support persistence so they are cleaner for remoting to other tiers, it’s easier to switch to another persistence stack at a later date, etc.
· IPOCO is a subset of POCO which says that the objects don’t have to inherit from a particular base class but they either gain some benefit from implementing certain interfaces or may even be required to implement those interfaces.
· Prescriptive classes or generated classes represent the other end of the spectrum. In these scenarios, the classes typically inherit from a particular base class which works directly with the persistence layer. In many cases the classes are auto-generated from a model of some kind and users can then extend them using partial classes or the like. Prescriptive classes have the disadvantage of being more tied to the persistence layer, but they tend to have advantages when it comes to performance as well as providing a broader set of services to the app developer that they would otherwise have to write themselves.
The EF started out as a framework which only supported prescriptive classes. Based on customer feedback we decided that it would be very important to support a greater degree of persistence ignorance for some scenarios, but we also believe that the prescriptive classes are great for other scenarios. So, we expect that overtime we’ll need to support this whole spectrum.
For the first release of the EF, we will support prescriptive classes and IPOCO. That is, you can have classes that do not inherit from our base class, but they must implement certain interfaces and they must have specific attributes in order to work with the EF. Right now there is a set of three interfaces, of which one is required (IEntityWithChangeTracker which is used for the object to communicate to the EF when the values of its properties are changed), one is required for any object which participates in persisted relationships (IEntityWithRelationships -- of course almost every object in a real system will participate in relationships so this one is pretty much also required), and one which is optional (IEntityWithKey – if you implement this then your object must have a property for storing the EntityKey, but in return parts of the system become faster/easier). For more information, see Implementing Custom Data Class Interfaces (Entity Framework).
In future releases, we will work to make the remaining interfaces optional as well as to make it possible not to have any specific attributes on the classes but instead to specify all of that metadata in some other form outside the assembly containing the classes that will be persisted, but we were just unable to get all the way there in the first release.
2.3. Is it recommended to share one global ObjectContext instance across my application?
It depends on the scenario. For single-threaded rich-client applications sharing a global ObjectContext may make sense--it may even provide advantages since identity resolution will reduce the number of in-memory objects as they are re-used across queries. You do have to be careful, though, to carefully manage the memory consumption of your application, because the ObjectContext will maintain a reference to every entity retrieved through it unless you use a NoTracking query or explicitly detach it. For more information, see Managing Resources in Object Services (Entity Framework).
For asp.net and web service applications, we generally don't recommend sharing a single global ObjectContext for a number of reasons, including threading issues (ObjectContext is not thread-safe), working set (since the context keeps references to objects retrieved through it as mentioned above), and data consistency (as the data in the database evolves over time it can get out of sync with the data in your local objects unless you explicitly query with an OverwriteChanges MergeOption).
It should also be noted, though, that it is possible to share a single ObjectContext across multiple EntityDataSource instances on an asp.net page. This should be managed carefully to avoid conflicts between the actions of the data sources, but it can provide some performance benefit. For more information see Object Context Life-Cycle Management (EntityDataSource).
3. Business Logic
3.1. How to write custom logic behind a "getter" or "setter"?
A lot has been done in Entity Framework to support adding business logic to the setters of the generated classes. With the introduction of partial methods for property changing and property changed users can write their custom business logic. Currently we don't have a plan for partial methods for the getters, but again you can write your own classes rather than just using the generated classes. One simple way to write your own classes is to let the system generate the classes for you once and then modify those and don't generate after that. Or you can completely write your own classes (IPOCO is the information you want to look for in the documentation). If you don't want to write your own classes, you can customize the code generation process to add additional statements to either the getters or setters. For more information, see Customizing Objects (Entity Framework).
3.2. Is it possible to write logic which distinguishes between user code calls to the data class and framework materialization of the class?
Unfortunately there isn't a system in place to allow you to easily distinguish between cases where the system is materializing an entity and user code is calling a constructor or setter. That's something we've talked about adding but currently is unlikely to make v1.
3.3. How to execute custom code on SaveChanges call?
ObjectContext has a SavingChanges event which is fired whenever SaveChanges is called on the context before any changes are persisted to the database. There is also an OnContextCreated partial method which is called from the context constructor and can be used to subscribe a handler to that event. This event handler can be used to enforce business logic which involves multiple entities. For more information, see How to: Execute Business Logic When Saving Changes (Entity Framework).
3.4. How do I write business logic which validates interactions between multiple properties on an entity?
Entity Framework allows creating a Validate method that can be overridden for every concrete type in the system. Here is how to do it:
1. Create an abstract type in your model from which all of your concrete types inherit or an interface which all of your entities will implement on their partial class. Add to the abstract class or interface a Validate method which can be overridden in the various concrete classes as appropriate.
2. Create an event handler for the SavingChanges event on the object context which goes through all of the inserted or updated entities (found by examining the ObjectStateManager) and calls the Validate method.
In future releases we'll look into ways to make this even easier for generated classes using partial methods and other mechanisms.
4. Code Generation
4.1. How can I add custom attributes to my generated classes? What is the extensibility story in Entity Framework for more advanced code generation scenarios?
The code generation system in the entity framework is built on top of a public API which you may call yourself in order to have finer grained control over the code generation process. See <http://blogs.msdn.com/dsimmons/archive/2007/09/01/ef-codegen-events-for-fun-and-profit-aka-how-to-add-custom-attributes-to-my-generated-classes.aspx>for more details. You can also fit these customizations into visual studios extension mechanisms. For more information see < http://blogs.msdn.com/adonet/archive/2008/01/24/sampleedmxcodegenerator-sources.aspx >.
4.2. Is there any way to use public, easily modifiable templates for EF code generation?
There’s an early version of a T4 template for code gen available at http://blogs.msdn.com/dsimmons/archive/2008/10/27/using-t4-templates-to-generate-ef-classes.aspx. It is possible, though, to use any of a number of template-based code generation systems to create EF-compatible entity classes—T4 is just one of the options. With IPOCO support in EF v1, the classes generated need to include certain attributes and implement certain interfaces (see Question 2.2 for more info), but within those constraints, there is still quite a bit of flexibility possible in the code for the entities.
5. Data Classes
5.1. Is it required to use the code generation tool? Can we hand author entity classes?
The entity framework most certainly does not require code generation. There are facilities for code generation and some of the UI/designer surface is geared toward those scenarios because they work well in a number of situations, but it is also possible to author your own classes by hand, implement a few key interfaces and use the entity framework that way. Your classes can but do not have to inherit from a common base class which is used in our generated classes. That said, this is something which we intend to make much easier in future releases. The long term goal is to support full persistence ignorance with the ability to opt-in to persistence awareness when/as needed. For more information, see Customizing Objects (Entity Framework).
5.2. Is it recommended to modify tool generated classes?
No, because if you do, then you won't be able to regenerate them without losing your changes. The recommended approach is to add functionality to the generated classes in partial classes in separate files. For the case of things which cannot be added in a partial class, like adding attributes to the generated classes or methods, the code generation process can be customized by calling the public code generation API instead of using the commandline or vs wizard tools for that purpose.
5.3. Does Entity Framework require objects with public empty constructors?
While the default generated classes have an automatically supplied public parameterless constructor, there's nothing in the framework that requires this to be so. There must be a parameterless constructor, but it can be private. You can try a simple example by taking the generated classes and just adding in a private parameterless constructor. At that point the generated factory method will work to create instances for users, but the system will just use the private parameterless constructor to materialize objects that are the results of queries. Another request which we have gotten is to support mapping directions so that even materialization of queries will go through factory methods, and that's something we will likely support in a future release but won't be supported in v1.
5.4. Does Entity Framework require objects with public accessors for properties that are to be stored in the database? Does EntityFramework support Read-Only properties?
The system does not require public settable properties for all fields that are persisted to the database. While the default generated classes have public properties for each persisted field, you can either write your own classes or set the access for the getter and setter in the designer (public, internal, protected or private).
5.5. Does EntityFramework support a private field to be mapped to the database?
The system doesn't currently allow you to attribute a field directly, and the designer doesn't support configuring this visually, but it is definitely possible to do. As noted above, however, you can just make the generated property private.
5.6. Does EntityFramework support inheritance for methods or properties that do not map to the database?
Certainly. You can add these methods or properties to the partial classes for your data objects. They will not be persisted, but derived types will inherit them.
5.7. Where has DoFinalConstruction() method gone?
Entity Framework no longer defines the method DoFinalConstruction or requires any of the mechanisms required in earlier CTPs of Entity Framework. For more information related to this topic refer to: