Organizing an EF4 data layer? - entity-framework

I am new to Entity Framework 4, and I am wondering, what's the best way to organize my data layer--the code that accesses EF4?
At this point, my data layer is set up like this:
DataStore class: Holds a reference to the EF4 ObjectContext, and contains methods to open, close, and persist the ObjectContext to storage.
Repository classes: One class for each entity, with methods to create, fetch, and delete entity objects.
Is there a better way to organize this functionality for EF4? I've looked for articles/blogs on the subject, but I'm not finding much. Any suggestions?

I use a generic repository for Entity Framework that makes access very easy. No need to write a separate repository for each entity, just:
MyDataContext ctx = new MyDataContext();
Repository<MyEntity, MyDataContext > myEntityRep = new Repository<MyEntity, MyDataContext>(ctx);
myEntityRep.Add(new MyEntity() {//property settings});
This repository totally abstracts the Entity model, allowing for creating, modifying, and deleting entities.

I prefer the repository classes for each entity type (I know them as DataMapper). One class for all queries easily becomes too monolithic hard to maintain.

Related

What problems can arise from storing a DbContext reference in a POCO object?

I am new to a 15 year old application. The team lead has started using Entity Framework + alongside existing WebForms + Sprocs.
Some POCOs (domain entities) in EF have properties containing references to the DbContext, usually parent objects at the top of an object graph. As I attempt to write tests, I continually get Context Disposed exceptions.
public EmployerService(int UserID, Entities entities) // business layer
{
this.UserID = UserID;
_entities = entities;
}
internal Employer CreateEmployer()
{
Employer employer = _entities.Employers.Create();
employer.MasterItem = _entities.MasterItems.Create();
employer.MasterItem.LastModified = _entities.ItemLastModifieds.Create();
employer.DBContext = _entities;
...
return employer;
}
More to the point, the project references are not clean. The POCOs reference Data and Business logic layers. I am building a case to get the DbContext references out of the POCO objects, but my search is just beginning.
So my question is, what design principles support or reject referencing the DAL layer from the POCOs?
Your DAL layer sneaks into Business Logic layer. Service now tightly coupled to Entity Framework (BTW I don't think it's good idea to add reference to EntityFramework.dll into your domain project). Consider we are moving to NHibernate. What you should change? Everybody would think it's a DAL task. But wait guys, I have some DAL in my domain! We should change EmployerService class.
So, keep your domain entities persistent ignorant. Especially keep them ignorant of concrete persistence technology you are using. And I think better place for Employer creation is a factory. Also I don't understand why you are not using simple constructors here? Looks like you can avoid Entity Framework usage during Employer creation.
The most vocal design principle here is that you're having problems with the current design.
DbContext is supposed to be used as a short-living - and it's not meant to be stored for later. The reference you're holding doesn't mean much, as it gets Disposed.
To the very least you should check if it's Disposed (you can do that by overriding Dispose I guess, setting a flag or something). But what to do if it is?
Basically, if you still do use it that way - make sure your POCO objects are `short-lived' as well - but that gets painful I'm sure.

Repository pattern with Entity Framework Entities vs Business Objects

In a code-first implementation of EF, used along with a Repository pattern, should the repository return business objects from the domain model, or simple entities from the data model?
From what I can tell, the point of Repository is to return business objects, not entities, so that you can do work with them. But most of the code examples I find are returning data models instead, which seems like a bad idea to me because what if the data source changes?
If you are using CodeFirst development you can easily use your business object as the data model as well. You can write Ef mappings in a separate DLL to remove the dependency of EF to business model. If you want to change the data source to another one instead of EF you can keep the same Business(domain) classes for that as well.

Poco+Entity Framework 4. Where should I add my methods for working with Poco classes?

I've tried to use Entity Framework 4 and POCO for my MVC 3 project. May be, I don't understand the main idea of this ORM, but the problem is following:
I added ADO .NET Entity Data Model and make model according to database.
I clicked Add Code Generation Item and added ADO .NET POCO Entity Generator.
It makes classes for every database table.
I want to add some methods to work with data (Add, Update, Delete, GetAll etc) to appropriate models.
For LINQTOSQL I added partial classes and placed them to Models. But now I can't do it because:
a) Models folder has classes with the same names, which was created by POCO.
b) If I place my partial class in the another folder, it will be another namespace - so, such classes won't be partial one.
c) If I place my code in POCO classes, it can be destroyed during update POCO.
How can I use it? Where sould I place my methods for data working?
Is the best way to make for POCO and EF the other project - http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx?
First of all you don't have to write your CRUD inside POCO,
There are many places where you can do it like in edmx.cs file or write one more layer which is called as CRUD Services which handles the Database operations using context object.
Now coming to your questions,
Create separate Models folder and place the Model classes in there.
Your Model class may like this,
EmployeeDepartmentModel
{
prop EmpList List(Emp);
prop DeptList List(Dept);
//Emp and Dept are my POCOs
}
So now I have to fill both of these list(Your CRUD question),
For that, I will Create one method in Controller class(its better to write such logic in some another library, but for time being I suggest you to create in Controller),
FillTheModel()
{
EmployeeDepartmentModel.EmpList = EDMX.GetAllEmployees;
EmployeeDepartmentModel.DeptList = EDMX.GetAllDepartments;
}
Now you can bind this model with your view.
You can place the partial classes in another folder and modify the namespace.
I agree with allisewell, but if you really want to add parts to partial classes, give files another name,
e.g. MyPoco.Part2.cs or modify t4 template to name generated files
e.g. Poco.Generated.cs

How can I create a detached clone of an EF codefirst class for testing purposes?

I want to create an integration test which grabs an EF entity from the DB, clones it to a detached object, modifies it and then saves it back and compares it again to the original.
However, I was using AutoMapper to create the clone of the class, but it turns out this is also tracked or an alias to the original object. I need it to be completely detached from EF, and am able to do this outside of my repository class (i.e. not using any EF detach methods).
The reason for doing this is my EF class contains nested collections of other classes and EF doesn't handle persisting the whole object tree. Hence, my Update() method in my repository class handles this and I want my NUnit test to test this code. I want the test is to be able to quickly create a copy of my original class without EF tracking it.
Creating a cloned object containing current, original, or database
values The DbPropertyValues object returned from CurrentValues,
OriginalValues, or GetDatabaseValues can be used to create a clone of
the entity. This clone will contain the property values from the
DbPropertyValues object used to create it. For example:
using (var context = new UnicornsContext())
{
var unicorn = context.Unicorns.Find(1);
var clonedUnicorn = context.Entry(unicorn).GetDatabaseValues().ToObject();
}
Note that the object returned is not the entity and is not being
tracked by the context. The returned object also does not have any
relationships set to other objects.
The cloned object can be useful for resolving issues related to
concurrent updates to the database, especially where a UI that
involves data binding to objects of a certain type is being used. (See
Part 9 for more details on dealing with optimistic concurrency.)
*From http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx
Hope it can helps others
All troubles are gone once you're using EF 5+ where they introduced AsNoTracking() method.
The line below returns an unlinked instance, so all the context won't be aware about any changes in that instance:
context.Clients.AsNoTracking().FirstOrDefault(item => item.Id == id);
If Clients has a reference to Address and you want an unlinked instance of it too, just use an Include:
context.Clients
.Include("Address").AsNoTracking()
.FirstOrDefault(item => item.Id == id);
If it is a test you can do anything and you don't have to be binded to any architectural approach like repository. Your repository probably receive context as injection so you can have access to it. Another point is that I don't believe that AutoMapper will create tracked entity.
The one way to make a copy of the class is using serialization which by default saves only public fields (Xml serialization or DataContract serialization). Serialize the object and deserialize it back to a new instance. Serialization will save the whole object graph and deserialized object graph will be detached. Just be aware that that those serializations don't likes cyclic references in object graph (navigation property from A to B and from B to A from cycles). Serialization is also too much aggresive so it can traverse the graph more deeply then you want - this can be especially dangerous in many to many relations.
The best approach is using either ICloneable interface and implement Clone or define support methods which will do different clones with required depth.
Here is another approach for clonning EntityObject based entities. It is tough code, especially part with Reflection.Emit. But this will not help you because code-first is using POCOs.

Entity Framework as Repository and UnitOfWork?

I'm starting a new project and have decided to try to incorporate DDD patterns and also include Linq to Entities. When I look at the EF's ObjectContext it seems to be performing the functions of both Repository and Unit of Work patterns:
Repository in the sense that the underlying data level interface is abstracted from the entity representation and I can request and save data through the ObjectContext.
Unit Of Work in the sense that I can write all my inserts/updates to the objectContext and execute them all in one shot when I do a SaveChanges().
It seems redundant to put another layer of these patterns on top of the EF ObjectContext? It also seems that the Model classes can be incorporated directly on top of the EF generated entities using 'partial class'.
I'm new at DDD so please let me know if I'm missing something here.
I don't think that the Entity Framework is a good implementation of Repository, because:
The object context is insufficiently abstract to do good unit testing of things which reference it, since it is bound to the DB access. Having an IRepository reference instead works much better for creating unit tests.
When a client has access to the ObjectContext, the client can do pretty much anything it cares to. The only real control you have over this at all is to make certain types or properties private. It is hard to implement good data security this way.
On a non-trivial model, the ObjectContext is insufficiently abstract. You may, for example, have both tables and stored procedures mapped to the same entity type. You don't really want the client to have to distinguish between the two mappings.
On a related note, it is difficult to write comprehensive and well-enforce business rules and entity code. Indeed, whether or not it this is even a good idea is debatable.
On the other hand, once you have an ObjectContext, implementing the Repository pattern is trivial. Indeed, for cases that are not particularly complex, the Repository is something of a wrapper around the ObjectContext and the Entity types.
I would say that you should look at the ObjectContext as your UnitOfWork, and not as a repository.
An ObjectContext cannot be a repository -imho- since it is 'to generic'.
You should create your own Repositories, which have specialized methods (like GetCustomersWithGoldStatus for instance) next to the regular CRUD methods.
So, what I would do, is create repositories (one for each aggregate-root), and let those repositories use the ObjectContext.
I like to have a repository layer for the following reasons:
EF gotcha's
When you look at some of the current tutorials on EF (Code First version), it is apparent there's a number of gotcha's to be handled, particularly around object graphs (entities containing entities) and disconnected scenarios. I think a repository layer is great for wrapping these up in one place.
A clear picture of data access mechanisms
A repository gives a specific picture as to how the BL is accessing and updating the data store. It exposes methods that have a clear single purpose, and can be tested independently of the BL. Standard example from the textbooks, Find() to find a single entity. A more application specific example, Clear() to clear down a db table.
A place for optimizations
Inevitably you come up against performance hits when using vanilla EF. I use the repository to hide the optimization mechanisms from the BL.
Examples,
GetKeys() to project cached keys from the tables (for Insert/Update decisions). The reading of key only is faster and uses less memory than reading the full entity.
Bulk load via SqlBulkCopy. EF will insert by individual SQL statements. If you want a single statement to insert multiple rows, SqlBulkCopy is a good mechanism. The repository encapsulates this and provides metadata for SqlBulkCopy. As well as the Insert method, you need a StartBatch() and EndBatch() method, which is also an argument for a UnitOfWork layer.