Sie sind auf Seite 1von 4

Entity Framework in the Enterprise

Notes by Julie Lerman


UI - Service Layer - Bus Layer - Repository/Unit of Work Data Layer - Database
EF should stay in the data layer.
Split your context in smaller bounded contexts.

Bounded DbContext

Inspired on "Domain-Driven Design by Eric Evans"


(domaindrivendesign.org)
All your navigation properties get pulled into the model.
Transition between context by id or by object.
Entity with property that is not persisted in the database:
public decimal LineTotal { get; set; } ... In map class add
Ignore(t => t.LineTotal)
Do not include navigation in the context: In
OnModelCreating add modelBuilder.Ignore<T>();
Make sure non related is included: In OnModelCreating
add modelBuilder.Entity<T>();
Migrations and creations: Add one model that includes all
of your tables and use this one.
Put each context in it's own project.
Put the mappings also in their separated project. eg.
BaseDataLayer - CompanyDatabaseInitializers CustomerServiceBoundedContext - DataLayerMappings DomainClasses - ReturnsBoundedContext SalesBoundedContext
Use EF powertools to visualize your context and see what

will be pulled in.


And then cherry pick what you need (eg. probably do not
need the relationships)

Repositories and Unit of Work

Encapsulate Redundant Data Access Code


GetCustomerById(cid), GetAllCustomers,
GetCurrentCustomers, GetLocalCustomers,
GetFilteredCustomers
RemoveCustomer, AddCustomer
Install-Package entityframework
Install-Package t4scaffolding
scaffold repository DomainClasses.Customer
-DbContextType:SalesContext
Always use ctx.Customers.Find(id) cause it will not
roundtrip when not needed.
DbSet.Add(root) - All elements State=Added - Insert for
each element, even if pre-existing in db
DbSet.Attach(root) - All elements State=Unchanged - Any
new records with missing FKs will throw
Context.Entry(root).State=EntityState - Context attaches
full graph, all entities State=Unchanged, Root (only) set to
specific state - Any new with missing FKs will throw
Disconnected Graph
Attaching to Context: all new -> DbSet.Add(customer)
Root new, existing unchanged:
Entry(customer).State=Added
Editing: Entry(customer).State=Modified then Entry(*each
item*).State=Modified
Root edited and added: DbSet.Add(customer) then
Entry(*each non added*).State=*correct state*

Make objects track their own state:


IObjectWithState
enum State { Added, Unchanged, Modified, Deleted }
public abstract class Person:IObjectWithState
[NotMapped]
public State State { get; set;}
Repository depends on the value of client-side State
Developer using repository MUST set client-side
State!
StateHelpers - EntityState ConvertState(State state)
ContextHelpers - ApplyStateChanges(this DbContext
context)
Difference between long running and short running context
(or implement two repos)
Let repositories share the same context (Unit of work)
Move save method to unit of work
CustomerRepository contains Unit of work that contains a
context
ReferencesContext
Especially when reading data:
_context.Customers.AsNoTracking();
A DbSet represents the collection of all entities in the
context, or that can be queried from the database, of a
given type.
DbSet object are created from a DbContext using the
DbContext.Set method
A DbContext instance represents a combination of the unit
of work and repository patterns such that it can be used to
query a database and group together changes that
will then be written back to the store as a unit. DbContext

is conceptually similar to ObjectContext.


Why build a repository on top op EF? EF is a repository!
Should you return an IQueryable from a repository
How much abstraction and refactoring? There will always
be more.

Automated Testing Overview

Unit Testing
Integration Testing
Interaction Testing
System Testing
User Interface Testing
1. Complete model with Seed method
2. Initialize Database for each integration test
3. Use a testing database that can get destroyed
frequently
Test your data annotations: test for
DbEntityValidationException
Fake Context & Fake Data
IDbSet<TEntity> : DbQuery<TEntity>, IDbSet<TEntity>,
IQueryable<TEntity>, IEnumerable<TEntity>, IQueryable,
IEnumerable where TEntity : class
(you can also use IObjectSet)
public abstract class MyFakeDbSet<T> : IDbSet<T>
where T : class, new()
{
}
Create implementation to override the find method
IUoW needs IContext
SalesPromotionAccessor (to hide the context and wrap it
with your unit of work)

Das könnte Ihnen auch gefallen