250 likes | 483 Views
.NET Database Technologies: Entity Framework additional notes – part 2. EF1 => EF4. “The 1.0 release of the Entity Framework was not a resounding success – developers found themselves fighting the framework” EF4 gives you the choice of how to work Database-first, model-first, code-first
E N D
.NET Database Technologies: Entity Framework additional notes – part 2
EF1 => EF4 • “The 1.0 release of the Entity Framework was not a resounding success – developers found themselves fighting the framework” • EF4 gives you the choice of how to work • Database-first, model-first, code-first • Supports POCO entities for Persistence Ignorance
POCO support • EF1 entity classes inherit from EntityObject • Difficult to separate concerns in application • Classes are difficult to unit test • For unit testing, want to “fake” persistent storage • Difficult to switch DAL technology • Can’t take existing classes and use EF1 • Need to redesign classes significantly to bind them to EF • EF4 allows you to use POCOs • Model classes can be completely ignorant of persistence mechanism
POCO classes • POCO classes must work in conjunction with EDM • Must mirror entities defines in EDM • However, EDM does not generate the classes • Set Code Generation Strategy to none in designer properties • Two ways to create classes • Write POCO code by hand • Use a T4 Template • Microsoft ADO.NET C# POCO Entity Generator • Download from www.visualstudiogallery.com • Right-click EDM designer surface and select Add Code Generation Item • Creates template for generating POCOs to match EDM
T4 • Text Template Transformation Toolkit • Code generation tool built into Visual Studio • Can be used in many different code generation scenarios • Template file has .tt extension • When a project has a .tt file, the template is processed at build time • Generated code file(s) associated with template in Solution Explorer, but can be moved elsewhere if required
Managing POCOs • Need to create a custom ObjectContext class • Should have an ObjectSet for each entity type • Needs to know name of EDMX file (passed in as a constructor parameter) to allow it to access mapping and storage information
Issues with POCOs – change tracking • Change tracking • Classes derived from EntityObject constantly communicate with ObjectContext • POCOs can’t do this • ObjectContext has to track changes to POCOs: • DetectChanges method • SaveOptions -> DetectAllChanges forces call to DetectChanges before saving • Default behaviour
Issues with POCOs – loading related data • EntityObject can load related data with Load method • e.g. employee.AddressesReference.Load() • Navigation property also has an EntityReference property • POCO does not have EntityReference properties • Need to load related data from context • e.g. context.LoadProperty<Employee>( employee, e => e.Addresses) • Can also support lazy loading with POCOs through dynamic proxies (see later)
Issues with POCOs – two-way relationships • Context forces EntityObject classes to be aware of two-way relationships and keeps relationships in sync • Options for doing this with POCOs: • Call DetectChanges method of context • Write code in POCO classes so that they manage their own relationships • Use dynamic proxies
Dynamic proxies • POCO classes can be wrapped by proxy classes which are created dynamically at runtime • Proxy class is derived from POCO class • POCO properties must be marked as virtual • Adds EF-specific behaviour which allows management of change tracking, lazy-loading and relationships in the same way as EntityObject classes • Client code works with POCO classes, but actual objects instantiated are proxies • EF uses reflection to find out about properties of POCOs and Reflection.Emit to dynamically generate IL code for proxy classes
POCOs and PI • POCOs do not need to derive from any persistence specific class • Do not use persistence specific collection types • Should use ICollection as collection property type • Requirement for properties to be virtual to support some capabilities through proxies • This does not violate PI – classes don’t need to know about what the derived classes will do • EF4 POCO support allows PI domain classes to be used
Using a repository • Rather than having client code query context directly it is common to use a repository • A repository “Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects” (Fowler) • Promotes testability • Can swap in fake context with affecting client/test code • Can program client to an interface for repository and define actual repository type through dependency injection • Allows DAL to be swapped easily • Context implements Unit of Work pattern, but often wrap this in UoW class/interface to allow further isolation of dependencies
IoC and Dependency Injection • Inversion of Control (IoC) • Objects do not create other objects on which they rely to do their work • Instead, they get the objects that they need from an outside source (for example, an xml configuration file) • Dependency Injection (DI) • This is done without the object intervention, usually by a container that passes constructor parameters and set properties • Castle Windsor is an example of a .NET DI container • Can manage dependencies for all kinds of service, not just persistence • http://msdn.microsoft.com/en-us/library/aa973811.aspx
Creating a repository • Pattern describes solution to problem, but does not strictly define how to write the code • Many variations on the Repository pattern are possible • You can design your own – there are plenty of articles and blog posts with examples to base it on • You can use a template to generate your basic implementation from an EDM • ADO.NET Unit Testable Repository Generator • Download from www.visualstudiogallery.com • EFRepository • Download from efrepository.codeplex.com
Model-First • All examples so far have been re-engineered from the database • Changes to the conceptual model were mapped to the original database • EF4 allows you to start by designing the conceptual model and then use that model to define the database • Model-First
Creating the conceptual model • Add new ADO.NET Entity Data Model item to project and select Empty Data Model in wizard • Add new Entities to model using Toolbox or right-click on designer surface • Add properties (scalar or complex) to each entity by right-clicking on entity • Set type of property in Properties window • Give each entity a key property • Add associations by right-clicking on surface or entities • Adding association creates navigation properties • Create inheritance hierarchy by specifying base class for new entities
Generate database • Right-click on designer surface and select Generate Database from the Model • Slightly misleading name • Database must exist – designer will generate DDL to add to database • Designer does not execute the DDL script it creates – have to do that separately • DDL Generation wizard allows you to specify the database, and creates connection string in app.config • Wizard adds SSDL and MSL portions to EDMX file and creates SQL script in project folder
DDL generation • Based on a T4 template • Table names come from EntitySet names • Property and association attributes set in designer will be reflected in column attributes, e.g. data types, cascade delete • Inheritance will be implemented with a TPT strategy • Many-to-many relationship implemented with a join table
Customising DDL generation • Possible to modify T4 template • Only template installed in VS2010 is SSDL to SQL 10.tt • Or use Entity Designer Database Generation Power Pack • Download from www.visualstudiogallery.com • Contains additional templates • Can force TPH strategy for inheritance • Provides capability to migrate existing database after making changes to model
Model-First and POCOs • Model-First approach is compatible with POCOs • Once EDMX has been created, you can create POCOs to mirror entities and ObjectContext class to manage them • Alternatively, the entities you create in the designer can be based on knowledge of existing POCO classes
Code-First • Avoid altogether working with visual model • Build your model with POCO classes • Moving towards true Domain Driven Design • Microsoft consulted with a Data Programmability Advisory Council which included Fowler, Evans and Nilsson • Currently this feature is a CTP, not included in the release of VS2010 • Need to download and install • Add reference to Microsoft.Data.Entity.Ctp.dll which is installed in Program Files\Microsoft ADO.NET Entity Framework Feature CTP5\Binaries • Add using System.Data.Entity where required
What does Code-First do? • You need to create POCOs and a context class which inherits from DbContext • Defines DbSet property to store a set of each entity class • At runtime it reads your class definitions and creates in-memory representation of CSDL, MSL and SSDL • Looks for connection string that has the same name as the context class • Uses convention-based persistence mapping • Convention over configuration • Creates database if it doesn’t already exist (SQL CE and SQL Express)
Customising mapping • Override OnModelCreating event of DbContext and use ModelBuilder class to customise mapping • Change table names • Customise column/property mapping • Split a table across multiple types • http://weblogs.asp.net/scottgu/archive/2010/07/23/entity-framework-4-code-first-custom-database-schema-mapping.aspx • Data annotation attributes • Specify keys, string lengths, etc • http://blogs.msdn.com/b/efdesign/archive/2010/03/30/data-annotations-in-the-entity-framework-and-code-first.aspx
EF4 options - summary • Database-First • Define model and mappings in EDMX • Entities are EntityObjects or POCOs • Model-First • Define model in EDMX • Entities are EntityObjects or POCOs • Code-First • Define model with POCOs • Mappings defined by convention or ModelBuilder/annotations • Entities are POCOs
Profiling EF • Profile at server • SQL Server Profiler • Profile at client • EF Profiler • http://efprof.com/ • Not free!