My blog about application development on the .NET platform and Windows®.

Implementing a generic data access layer using Entity Framework

This post is about how you can develop a generic data access layer (DAL) with full CRUD (Create, Read, Update and Delete) support using Entity Framework 5 with plain old CLR objects (POCOs) and short-lived contexts in a disconnected and stateless N-tier application.

Entity Framework (EF) is Microsoft’s recommended data access technology when building new .NET applications. It is an object-relational mapping framework (ORM) that enables developers to work with relational data using domain-specific objects without having to write code to access data from a database.

EF provides three options for creating the conceptual model of your domain entities, also known as the entity data model (EDM); database first, model first and code first. With both the model first and code first approaches the presumption is that you don’t have an existing database when you start developing the application and a database schema is created based on the model. As databases within enterprise environments are generally designed and maintained by database administrators (DBAs) rather than developers, this post will use the database first option where the EDM becomes a virtual reflection of a database or a subset of it.

Typically when you are doing database first development using EF you are targeting an already existing database but for testing and demo purposes you may of course generate a new one from scratch. There is a walkthrough on how you can create a local service-based database in Visual Studio 2012 available on MSDN here.

The database used in this example is a very simple one containing only the two tables listed below. There is a one-to-many relationship between the Department and Employee tables meaning an employee belongs to a single department and a department can have several employees.

CREATE TABLE [dbo].[Department] (
    [DepartmentId] INT          IDENTITY (1, 1) NOT NULL,
    [Name]         VARCHAR (50) NULL,
    PRIMARY KEY CLUSTERED ([DepartmentId] ASC)
);

CREATE TABLE [dbo].[Employee] (
    [EmployeeId]   INT          IDENTITY (1, 1) NOT NULL,
    [DepartmentId] INT          NOT NULL,
    [FirstName]    VARCHAR (20) NOT NULL,
    [LastName]     VARCHAR (20) NOT NULL,
    [Email]        VARCHAR (50) NULL,
    PRIMARY KEY CLUSTERED ([EmployeeId] ASC),
    CONSTRAINT [FK_Employee_Department] FOREIGN KEY ([DepartmentId])
    REFERENCES [dbo].[Department] ([DepartmentId])
);

N-tier architecture

A large enterprise application will typically have one or more databases to store data and on top of this a data access layer (DAL) to access the database(s). On top of this there may be some repositories to communicate with the DAL, a business layer containing logic and classes representing the business domain, a service layer to expose the business layer to clients and finally some user interface application such as a WPF desktop application or an ASP.NET web application.

User interface layer
WPF / ASP.NET / Console App / WinRT / …
Service layer
WCF / ASMX / …
Business logic layer
Data access layer
EF / ADO.NET / …
Database
SQL Server / Oracle / MySql / …

Data access layer (DAL)

The DAL is simply a C# class library project where you define the model generated from the existing database along with the generic implementation for reading and modifying the data in the database. It is the only layer in the application that will actually know anything about and have any dependencies on EF. Any user interface code should only communicate with the service or business layer and don’t have any references to the DAL.

1. Start by creating a new class library project (Mm.DataAccessLayer) and add a new ADO.NET Entity Data Model to it. Choose the “Generate from database” option in the Entity Data Model wizard. The wizard lets you connect to the database and select the Department and Employee tables to be included in the model.

wizard2 Entity Data Model

Once the wizard has completed the model is added to your project and you are able to view it in the EF Designer. By default all generated code including the model classes for the Department and Employee entities sits in the same project.

Separating entity classes from EDMX

Again, in an enterprise level application where separation of concerns is of great importance you certainly want to have your domain logic and your data access logic in separate projects. In other words you want to move the generated model (Model.tt) to another project. This can easily be accomplished by following these steps:

2. Add a new class library project (Mm.DomainModel) to the solution in Visual Studio.
3. Open File Explorer (right-click on the solution in Visual Studio and choose the “Open Folder in File Explorer” option) and move the Model.tt file to the new project folder.
4. Back in Visual Studio, include the Model.tt file in the new project by clicking on the “Show All Files” icon at the top of the Solution Explorer and then right-click on the Model.tt file and choose the “Include In Project” option.
5. Delete the Model.tt file from the DAL project.
6. For the template in the new domain model project to be able to find the model you then need to modify it to point to the correct EDMX path. You do this by setting the inputFile variable in the Model.tt template file to point to an explicit path where to find the model:

const string inputFile = @"../Mm.DataAccessLayer/Model.edmx";

Once you save the file the entity classes should be generated in the domain model project. Note that if you make any changes to the model in the DAL project later on you are required to explicitly update your model classes. By right-click on the Model.tt template file and choose “Run Custom Tool” the entity classes will be regenerated to reflect the latest changes to the model.

7. As the context by default expects the entity classes to be in the same namespace, add a using statement for their new namespace to the Model.Context.tt template file in the DAL project:

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using Mm.DomainModel; <!-- Added -->
<#
if (container.FunctionImports.Any())
{
#>
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
<#
}
#>

8. Finally, you need to add a reference from the DAL project to the domain model project in order for it to compile.

DbContext

In an EF-based application a context is responsible for tracking changes that are made to the entities after they have been loaded from the database. You then use the SaveChanges method on the context to persist the changes back to the database.

By default EDMs created in Visual Studio 2012 generates simple POCO entity classes and a context that derives from DbContext and this is the recommended template unless you have a reason to use one of the others listed on MSDN here.

The DbContext class was introduced in EF 4.1 and provides a simpler and more lightweight API compared to the EF 4.0 ObjectContext. However it simply acts like a wrapper around the ObjectContext and if you for some reason need the granular control of the latter you can implement an extension method – extension methods enable you to “add” methods to existing types without creating a new derived type – to be able to convert the DbContext to an ObjectContext through an adapter:

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;

namespace Mm.DataAccessLayer
{
    public static class DbContextExtensions
    {
        public static ObjectContext ToObjectContext(this DbContext dbContext)
        {
            return (dbContext as IObjectContextAdapter).ObjectContext;
        }
    }
}

Encapsulating data access into repositories

A repository is responsible for encapsulating the data access code. It sits between the DAL and the business layer of the application to query the data source for data and map this data to an entity class, and it also persists changes in the entity classes back to the data source using the context.

A repository typically implements an interface that provides a simple set of methods for the developer using the repository to code against. Using an interface the consumer doesn’t need to know anything about what happens behind the scenes, i.e. whether the DAL uses EF, another ORM or manually creating connections and commands to execute queries against a data source. Besides the abstraction it brings it’s also great if you are using dependency injection in your application.

By using a generic repository for querying and persisting changes for your entity classes you can maximize code reuse. Below is a sample generic interface which provides methods to query for all entities, specific entities matching a given where predicate and a single entity as well as methods for inserting, updating and removing an arbitrary number of entities.

9. Add the below interface named IGenericDataRepository to the Mm.DataAccessLayer project.

using Mm.DomainModel;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Mm.DataAccessLayer
{
    public interface IGenericDataRepository<T> where T : class
    {
        IList<T> GetAll(params Expression<Func<T, object>>[] navigationProperties);
        IList<T> GetList(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
        T GetSingle(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
        void Add(params T[] items);
        void Update(params T[] items);
        void Remove(params T[] items);
    }
}

IList vs IQueryable

Note that the return type of the two Get* methods is IList<T> rather than IQueryable<T>. This means that the methods will be returning the actual already executed results from the queries rather than executable queries themselves. Creating queries and return these back to the calling code would make the caller responsible for executing the LINQ-to-Entities queries and consequently use EF logic. Besides, when using EF in an N-tier application the repository typically creates a new context and dispose it on every request meaning the calling code won’t have access to it and therefore the ability to cause the query to be executed. Thus you should always keep your LINQ queries inside of the repository when using EF in a disconnected scenario such as in an N-tier application.

Loading related entities

EF offers two categories for loading entities that are related to your target entity, e.g. getting employees associated with a department in this case. Eager loading uses the Include method on the DbSet to load child entities and will issue a single query that fetches the data for all the included entities in a single call. Each of the methods for reading data from the database in the concrete sample implementation of the IGenericDataRepository<T> interface below supports eager loading by accepting a variable number of navigation properties to be included in the query as arguments.

10. Add a new class named GenericDataRepository to the MM.DataAccessLayer project and implement the IGenericDataRepository<T> interface .

using Mm.DomainModel;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;

namespace Mm.DataAccessLayer
{
    public class GenericDataRepository<T> : IGenericDataRepository<T> where T : class
    {
        public virtual IList<T> GetAll(params Expression<Func<T, object>>[] navigationProperties)
        {
            List<T> list;
            using (var context = new Entities())
            {
                IQueryable<T> dbQuery = context.Set<T>();

                //Apply eager loading
                foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
                    dbQuery = dbQuery.Include<T, object>(navigationProperty);
                
                list = dbQuery
                    .AsNoTracking()
                    .ToList<T>();
            }
            return list;
        }

        public virtual IList<T> GetList(Func<T, bool> where, 
             params Expression<Func<T,object>>[] navigationProperties)
        {
            List<T> list;
            using (var context = new Entities())
            {
                IQueryable<T> dbQuery = context.Set<T>();
                
                //Apply eager loading
                foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
                    dbQuery = dbQuery.Include<T, object>(navigationProperty);

                list = dbQuery
                    .AsNoTracking()
                    .Where(where)
                    .ToList<T>();
            }
            return list;
        }

        public virtual T GetSingle(Func<T, bool> where,
             params Expression<Func<T, object>>[] navigationProperties)
        {
            T item = null;
            using (var context = new Entities())
            {
                IQueryable<T> dbQuery = context.Set<T>();
                
                //Apply eager loading
                foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
                    dbQuery = dbQuery.Include<T, object>(navigationProperty);

                item = dbQuery
                    .AsNoTracking() //Don't track any changes for the selected item
                    .FirstOrDefault(where); //Apply where clause
            }
            return item;
        }
        
        /* rest of code omitted */
    }
}

For example, here’s how you would call the GetAll method to get all departments with its employees included:

IGenericDataRepository<Department> repository = new GenericDataRepository<Department>();
IList<Department> departments = repository.GetAll(d => d.Employees);

With lazy loading related entities are loaded from the data source by EF issuing a separate query first when the get accessor of a navigation property is accessed programmatically.

Dynamic proxies

For EF to enable features such as lazy loading and automatic change tracking for POCO entities, it can create a wrapper class around the POCO entity at runtime. There is a certain set of rules that your entity classes need to follow to get this proxy behavior. To get the instant change tracking behavior every property must be marked as virtual. For the lazy loading to work, those related properties that you want to be lazily loaded must be marked as virtual and those who point to a set of related child objects have to be of type ICollection. There is a complete list of the requirements for POCO proxies to be created available on MSDN here if you want more information.

Disconnected entities

However, in an N-tier application entity objects are usually disconnected meaning they are not being tracked by a context as the data is fetched using one context, returned to the client where there is no context to track changes and then sent back to the server and persisted back to the database using another instance of the context. Looking at the code above, a new instance of the context will be created and disposed for each method call and the AsNoTracking extension method – also added in EF 4.1 – is used to tell the context not to track any changes which may result in better performance when querying for a large number of entities. When using short-lived contexts like this, you should disable lazy loading. If you don’t an exception saying the context has been disposed will be thrown whenever a non-initialized navigation property is accessed from anywhere outside the context’s scope.

11. Lazy loading and dynamic proxy creation is turned off for all entities in a context by setting two flags on the Configuration property on the DbContext as shown below. Both these properties are set to true by default.

namespace Mm.DataAccessLayer
{
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using Mm.DomainModel;
    
    public partial class Entities : DbContext
    {
        public Entities()
            : base("name=Entities")
        {
            Configuration.LazyLoadingEnabled = false;
            Configuration.ProxyCreationEnabled = false;
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public DbSet<Department> Departments { get; set; }
        public DbSet<Employee> Employees { get; set; }
    }
}

Root vs Graphs

When it comes to persisting changes to the database you need to decide whether your CUD methods should accept an entire graph of entities or only a single root entity to be passed in. A graph of entities is a number of entities that reference each other. For example, when you want to insert a new Department entity to the database by passing it to the repository’s Add method it might have related Employee objects. In this case the Employee objects belong to the graph and the Department object is the root entity.

EntityState

On the server side, things will get easier if you decide to not support graphs. In this case you could expose an Add method and an Update method for each entity type and these methods would only operate on a standalone instance rather than a graph of entities. EF makes it simple to implement these methods. It is all about setting the state of the passed in entity object. An entity can be in one of five states as defined by the System.Data.EntityState enumeration:

Added: the entity is being tracked by the context but hasn’t been added to the database yet.

Unchanged: the entity is being tracked by the context, it exists in the database but its property values have not been changed since it was fetched from the database.

Modified: the entity is being tracked by the context, it exists in the database and some or all of its property values have been modified since it was fetched from the database

Deleted: the entity is being tracked by the context, it exists in the database but will be deleted on the next call to the SaveChanges method.

Detached: the entity is not being tracked by the context at all.

When the context’s SaveChanges method is called it decides what to do based on the entity’s current state. Unchanged and detached entities are ignored while added entities are inserted into the database and then become Unchanged when the method returns, modified entities are updated in the database and then become Unchanged and deleted entities are deleted from the database and then detached from the context.

DbSet.Entry

You can explicitly change the state of an entity by using the DbSet.Entry method. There is no need to attach the entity to the context before using this method as it will automatically do the attachment if needed. Below is the implementation of the generic repository’s Add method. It explicitly sets the state of the entity to be inserted into the database to Added before calling SaveChanges to execute and commit the insert statement.

public virtual void Add(params T[] items)
{
    using (var context = new Entities())
    {
        foreach (T item in items)
        {
            context.Entry(item).State = System.Data.EntityState.Added;
        }
        context.SaveChanges();
    }
}

The implementation for the Update and Remove methods are very similar to the Add method as shown below. Note that all exception handling has been omitted for brevity in the sample code.

public virtual void Update(params T[] items)
{
    using (var context = new Entities())
    {
        foreach (T item in items)
        {
            context.Entry(item).State = System.Data.EntityState.Modified;
        }
        context.SaveChanges();
    }
}

public virtual void Remove(params T[] items)
{
    using (var context = new Entities())
    {
        foreach (T item in items)
        {
            context.Entry(item).State = System.Data.EntityState.Deleted;
        }
        context.SaveChanges();
    }
}

Also note that all methods have been marked as virtual. This allows you to override any method in the generic repository by adding a derived class in cases where you need some specific logic to apply only to a certain type of entity. To be able to extend the generic implementation with methods that are specific only to a certain type of entity, whether it’s an initial requirement or a possible future one, it’s considered a good practice to define a repository per entity type from the beginning. You can simply inherit these repositories from the generic one as shown below and add methods to extend the common functionality based on your needs.

12. Add interfaces and classes to represent specific repositories for the Department and Employee entities to the DAL project.

using Mm.DomainModel;

namespace Mm.DataAccessLayer
{
    public interface IDepartmentRepository : IGenericDataRepository<Department>
    {
    }

    public interface IEmployeeRepository : IGenericDataRepository<Employee>
    {
    }

    public class DepartmentRepository : GenericDataRepository<Department>, IDepartmentRepository
    {
    }

    public class EmployeeRepository : GenericDataRepository<Employee>, IEmployeeRepository
    {
    }
}

Business layer

As mentioned before, the repository is located somewhere between the DAL and the business layer in a typical N-tier architecture. The business layer will use it to communicate with the database through the EDM in the DAL. Any client application will be happily unaware of any details regarding how data is fetched or persisted on the server side. It’s the responsibility of the business layer to provide methods for the client to use to communicate with the server.

13. Add a new project (Mm.BusinessLayer) to the solution with references to the DAL project (Mm.DataAccessLayer) and the project with the domain classes (Mm.DomainModel). Then add a new interface and a class implementing this interface to it to expose methods for creating, reading, updating and deleting entities to any client application.

Below is a sample implementation. In a real world application the methods in the business layer would probably contain code to validate the entities before processing them and it would also be catching and logging exceptions and maybe do some caching of frequently used data as well.

using Mm.DomainModel;
using System.Collections.Generic;
using Mm.DataAccessLayer;

namespace Mm.BusinessLayer
{
    public interface IBusinessLayer
    {
        IList<Department> GetAllDepartments();
        Department GetDepartmentByName(string departmentName);
        void AddDepartment(params Department[] departments);
        void UpdateDepartment(params Department[] departments);
        void RemoveDepartment(params Department[] departments);

        IList<Employee> GetEmployeesByDepartmentName(string departmentName);
        void AddEmployee(Employee employee);
        void UpdateEmploee(Employee employee);
        void RemoveEmployee(Employee employee);
    }

    public class BuinessLayer : IBusinessLayer
    {
        private readonly IDepartmentRepository _deptRepository;
        private readonly IEmployeeRepository _employeeRepository;

        public BuinessLayer()
        {
            _deptRepository = new DepartmentRepository();
            _employeeRepository = new EmployeeRepository();
        }

        public BuinessLayer(IDepartmentRepository deptRepository,
            IEmployeeRepository employeeRepository)
        {
            _deptRepository = deptRepository;
            _employeeRepository = employeeRepository;
        }

        public IList<Department> GetAllDepartments()
        {
            return _deptRepository.GetAll();
        }

        public Department GetDepartmentByName(string departmentName)
        {
            return _deptRepository.GetSingle(
                d => d.Name.Equals(departmentName), 
                d => d.Employees); //include related employees
        }

        public void AddDepartment(params Department[] departments)
        {
            /* Validation and error handling omitted */
            _deptRepository.Add(departments);
        }

        public void UpdateDepartment(params Department[] departments)
        {
            /* Validation and error handling omitted */
            _deptRepository.Update(departments);
        }

        public void RemoveDepartment(params Department[] departments)
        {
            /* Validation and error handling omitted */
            _deptRepository.Remove(departments);
        }

        public IList<Employee> GetEmployeesByDepartmentName(string departmentName)
        {
            return _employeeRepository.GetList(e => e.Department.Name.Equals(departmentName));
        }

        public void AddEmployee(Employee employee)
        {
            /* Validation and error handling omitted */
            _employeeRepository.Add(employee);
        }

        public void UpdateEmploee(Employee employee)
        {
            /* Validation and error handling omitted */
            _employeeRepository.Update(employee);
        }

        public void RemoveEmployee(Employee employee)
        {
            /* Validation and error handling omitted */
            _employeeRepository.Remove(employee);
        }
    }
}

Client

A client application consuming the sever side code will only need references to the business layer and the entity classes defined in the Mm.DomainModel project. Below is a simple C# console application to test the functionality provided by the business layer. It’s important to note that there are no references or dependencies to EF in this application. In fact you could replace the EF-based DAL with another one using raw T-SQL commands to communicate with the database without affecting the client side code. The only thing in the console application that hints that EF may be involved is the connection string that was generated in the DAL project when the EDM was created and has to be added to the application’s configuration file (App.config). Connection strings used by EF contain information about the required model, the mapping files between the model and the database and how to connect to the database using the underlying data provider.

14. To be able to test the functionality of the business layer and the DAL, create a new console application and add references to the Mm.BusinessLayer project and the Mm.DomainModel project.

using Mm.BusinessLayer;
using Mm.DomainModel;
using System;
using System.Collections.Generic;

namespace Mm.ConsoleClientApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            IBusinessLayer businessLayer = new BuinessLayer();
            
            /* Create some departments and insert them to the database through the business layer */
            Department it = new Department() { Name = "IT" };
            Department sales = new Department() { Name = "Sales" };
            Department marketing = new Department() { Name = "Marketing" };
            businessLayer.AddDepartment(it, sales, marketing);

            /* Get a list of departments from the database through the business layer */
            Console.WriteLine("Existing departments:");
            IList<Department> departments = businessLayer.GetAllDepartments();
            foreach (Department department in departments)
                Console.WriteLine(string.Format("{0} - {1}", department.DepartmentId, department.Name));

            
            /* Add a new employee and assign it to a department */
            Employee employee = new Employee()
            {
                FirstName = "Magnus",
                LastName = "Montin",
                DepartmentId = it.DepartmentId
            };
            businessLayer.AddEmployee(employee);
            
            /* Get a single department by name */
            it = businessLayer.GetDepartmentByName("IT");
            if (it != null)
            {
                Console.WriteLine(string.Format("Employees at the {0} department:", it.Name));
                foreach (Employee e in it.Employees)
                    Console.WriteLine(string.Format("{0}, {1}", e.LastName, e.FirstName));
            };

            /* Update an existing department */
            it.Name = "IT Department";
            businessLayer.UpdateDepartment(it);

            /* Remove employee */
            it.Employees.Clear();
            businessLayer.RemoveEmployee(employee);
            
            /* Remove departments*/
            businessLayer.RemoveDepartment(it, sales, marketing);

            Console.ReadLine();
        }
    }
}

Output

Persisting disconnected graphs

While avoiding the complexity of accepting graphs of objects to be persisted at once makes life easier for server side developers, it potentially makes the client component more complex. As you may have noticed by looking at the code for the business layer above, you are also likely to end up with a large number of operations exposed from the server. If you do want your business layer to be able to handle graphs of objects to passed in and be persisted correctly, you need a way of determining what changes were made to the passed in entity objects in order for you to set their states correctly.

For example, consider a scenario when you get a Department object representing a graph with related Employee objects. If all entities in the graph are new, i.e. are not yet in the database, you can simply call the DbSet.Add method to set the state of all entities in the graph to Added and call the SaveChanges to persist the changes. If the root entity, the Department in this case, is new and all related Employee objects are unchanged and already existing in the database you can use the DbSet.Entry method to change the state of the root only. If the root entity is modified and some related items have also been changed, you would first use the DbSet.Entry method to set the state of the root entity to Modified. This will attach the entire graph to the context and set the state of the related objects to Unchanged. You will then need to identify the related entities that have been changed and set the state of these to Modified too. Finally, you may have a graph with entities of varying states including added ones. The best thing here is to use the DbSet.Add method to set the states of the related entities that were truly added to Added and then use the DbSet.Entry method to set the correct state of the other ones.

So how do you know the state of an entity when it comes from a disconnected source and how do you make your business layer able to persist a graph with a variety of objects with a variety of states? The key here is to have the entity objects track their own state by explicitly setting the state on the client side before passing them to the business layer. This can be accomplished by letting all entity classes implement an interface with a state property. Below is a sample interface and an enum defining the possible states.

namespace Mm.DomainModel
{
    public interface IEntity
    {
        EntityState EntityState { get; set; }
    }

    public enum EntityState
    {
        Unchanged,
        Added,
        Modified,
        Deleted
    }
}
/* Entity classes implementing IEntity */
public partial class Department : IEntity
{
    public Department()
    {
        this.Employees = new HashSet<Employee>();
    }
    
    public int DepartmentId { get; set; }
    public string Name { get; set; }
    
    public virtual ICollection<Employee> Employees { get; set; }

    public EntityState EntityState { get; set; }
}

public partial class Employee : IEntity
{
    public int EmployeeId { get; set; }
    public int DepartmentId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    
    public virtual Department Department { get; set; }

    public EntityState EntityState { get; set; }
}

With this solution, the business layer will know the state of each entity in a passed in graph assuming the states have been set correctly in the client application. The repository will need a helper method to convert the custom EntityState value to a System.Data.EntityState enumeration value. The below static method can be added to the GenericDataRepository<T> class in the DAL to takes care of this.

protected static System.Data.EntityState GetEntityState(Mm.DomainModel.EntityState entityState)
{
    switch (entityState)
    {
        case DomainModel.EntityState.Unchanged:
            return System.Data.EntityState.Unchanged;
        case DomainModel.EntityState.Added:
            return System.Data.EntityState.Added;
        case DomainModel.EntityState.Modified:
            return System.Data.EntityState.Modified;
        case DomainModel.EntityState.Deleted:
            return System.Data.EntityState.Deleted;
        default:
            return System.Data.EntityState.Detached;
    }
}

Next, you need to specify a constraint on the IGenericDataRepository<T> interface and the GenericDataRepository<T> class to ensure that the type parameter T implements the IEntity interface and then make some modifications to the CUD methods in the repository as per below. Note that the Update method will actually be able to do all the work now as it basically only sets the System.Data.EntityState of an entity based on the value of the custom enum property.

public interface IGenericDataRepository<T> where T : class, IEntity { ... }
public virtual void Add(params T[] items)
{
    Update(items);
}

public virtual void Update(params T[] items)
{
    using (var context = new Entities())
    {
        DbSet<T> dbSet = context.Set<T>();
        foreach (T item in items)
        {
            dbSet.Add(item);
            foreach (DbEntityEntry<IEntity> entry in context.ChangeTracker.Entries<IEntity>())
            {
                IEntity entity = entry.Entity;
                entry.State = GetEntityState(entity.EntityState);
            }
        }
        context.SaveChanges();
    }
}

public virtual void Remove(params T[] items)
{
    Update(items);
}

Also note they key to all this working is that the client application must set the correct state of an entity as the repository will be totally dependent on this. Finally, below is some client side code that shows how to set the state of entities and passing a graph of objects to the business layer.

using Mm.BusinessLayer;
using Mm.DomainModel;
using System;
using System.Collections.Generic;

namespace Mm.ConsoleClientApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            IBusinessLayer businessLayer = new BuinessLayer();
            
            /* Create a department graph with two related employee objects */
            Department it = new Department() { Name = "IT" };
            it.Employees = new List<Employee> 
            { 
                new Employee { FirstName="Donald", LastName="Duck", EntityState=EntityState.Added },
                new Employee { FirstName="Mickey", LastName="Mouse", EntityState=EntityState.Added }
            };
            it.EntityState = EntityState.Added;
            businessLayer.AddDepartment(it);

            /*Add another employee to the IT department */
            Employee employee = new Employee()
            {
                FirstName = "Robin",
                LastName = "Hood",
                DepartmentId = it.DepartmentId,
                EntityState = EntityState.Added
            };
            /* and change the name of the department */
            it.Name = "Information Technology Department";
            it.EntityState = EntityState.Modified;
            foreach (Employee emp in it.Employees)
                emp.EntityState = EntityState.Unchanged;
            it.Employees.Add(employee);
            businessLayer.UpdateDepartment(it);

            /* Verify changes by quering for the updated department */
            it = businessLayer.GetDepartmentByName("Information Technology Department");
            if (it != null)
            {
                Console.WriteLine(string.Format("Employees at the {0} department:", it.Name));
                foreach (Employee e in it.Employees)
                    Console.WriteLine(string.Format("{0}, {1}", e.LastName, e.FirstName));
            };

            /* Delete all entities */
            it.EntityState = EntityState.Deleted;
            foreach (Employee e in it.Employees)
                e.EntityState = EntityState.Deleted;
            businessLayer.RemoveDepartment(it);

            Console.ReadLine();
        }
    }
}

Output


147 Comments on “Implementing a generic data access layer using Entity Framework”

  1. Very nice article!

    Is there a way to serialize a department with employees using wcf without modifying Model.tt to add [KnownType(typeof(Employee))] and what not?

  2. magnusmontin says:

    Hi Stefan,

    The KnownType attribute allows you to specify types that should be included for consideration during the deserialization. It’s typically used when the declared type for the information to be transmitted is a base class or an interface and the receiving endpoint cannot determine in advance which type is actually sent: http://msdn.microsoft.com/en-us/library/ms730167.aspx

    In this case, where you have a Department type and an Employee type that are not really related to each other when it comes to the class hierarchy, it’s not necessary.

    You can choose to distribute the assembly that contains the entity classes to any client application that consumes the WCF service or create DTOs (Data Transfer Objects) that represents the data to be serialized and then map these to the entity objects. If you add a service reference in Visual Studio (VS) you can uncheck the CheckBox that says “Reuse types in referenced assemblies” in order for VS to generate the DataContracts.

    Keep in mind that data contracts should only ever contain data and not any behaviour as the message being passed between the client and service is a pure text-based serialized message.

  3. Brijesh Shah says:

    Hi Team,

    It is really nice example to learn. But when i follow the same steps. I am getting few errors. Can you provide us the zip file of this source code which we can compare with & find out our mistakes ?

  4. Brijesh Shah says:

    Very Nice Article here… But one question if you can answer…
    In the Console Application, Do we need to write following code ?

    foreach (Employee emp in it.Employees)
    emp.EntityState = EntityState.Unchanged;

    we are changing the Department Entity (Name Property) and adding one Employee in that Department. So, Do we really require to add these line ? which just represent the existing employee state is Unchanged ? what effect it will if we do not specify this ?

    Because in real time scenario, I suppose coder (Developer) will do all above but will not take care these

  5. magnusmontin says:

    Hi Brijesh,

    As the client side code first sets the EntityState property of the Employee objects to be added to the database to EntityState.Added, you then need to change their state to EntityState.Unchanged before passing them to the business layer again. If you don’t change the state from Added to Unchanged, a duplicate record will be added to the database for each entity having its EntityState property set to EntityState.Added.

    Remember, as the article states, that the key to be able to determine the state of a disconnected entity is to have the objects track their own state by explicitly setting the state on the client side before passing them to the business layer.

    However, you could reset the state of all entities to Unchanged in the business layer or data access layer once the changes have been persisted, i.e. after the SaveChanges method has been executed.

  6. shriji1111 says:

    Great…
    You’re correct If we didn’t change the state it will add the duplicate entry as the last state is added. Now, Here we have sequential lines of code from where we can identify this easily & can remember or can review from previous statement.

    So, in real world application, Data may inserted/ updated from different areas or different classes/ methods/ objects. So, in that case, we can’t be sure about those right ?

    If you agreed with me, then there is only solution left is what you described in last passage that change the entitystate once the SaveChanges Method called. that means we need to include
    it.EntityState = EntityState.Unchanged instead of emp.EntityState = EntityState.Unchanged
    and this line would be just below businessLayer.AddDepartment(it); line (where we add department “IT” at the first time)

    and such every operation we need to make sure to change the status to Unchanged after completion & for that we should use business layer class

    Am I right ?

  7. The rule is that any client side class or method is responsible for setting the correct entity state for each entity object in the graph before calling the business layer to persist the changes.

    This means that if you don’t want an UPDATE statement to be generated for the Department object when you call the UpdateDepartment method, you should set its EntityState to Unchanged. In the sample code, I change its name to “Information Technology Department” after adding it and hence set the EntityState to Modified before calling the UpdateDepartment method.

    If you choose to reset the state of all entity objects to Unchanged in the business layer or data access layer once the changes have been persisted, you don’t need to explicitly set the state to Unchanged on the client side (foreach (Employee emp in it.Employees){ emp.EntityState = EntityState.Unchanged }) before passing the same entity to the business layer again.

    The sample code doesn’t reset the states on the server side and consequently needs to set the EntityState to Unchanged for all Employee objects that have already been persisted (added) during the first call to the AddDepartment method before calling the UpdateDepartment method.

    How to handle concurrency conflicts that may occur is out of the scope of this article. If you don’t set up EF to detect such conflicts, whoever updates the database last overwrites any previous changes.

  8. Mehrsa Fereidoonian says:

    Thanks for your very useful article…..
    how can i download the source of the program????

  9. Hi Mehrsa,

    I am glad you liked the article. The code isn’t available for download at this time but everything you need to be able to follow and compile the sample solution should be found in the article.

  10. Jerrico Wills says:

    Very good article Magnus,
    I am, however, having an issue. I will first admit that I am new to using EF. I have created all the tiers but my solution has included only one stored procedure. This procedure does not pull all columns from a table. Instead it calls a user function. The solution is compiling okay, but when I run, I get this error:

    The type ‘my_stored_proc’ is mapped as a complex type. The Set method, DbSet objects, and DbEntityEntry objects can only be used with entity types, not complex types.

    I have searched with no luck yet and I have tried deleting the function imports and the complex types in the model browser and ran the Add Function Import utility but the error persists. I’m sure I’m just not grasping exactly what is going on. Can you point me in the right direction to solving this issue? Thank you!

  11. Hi Jerrico,

    The easiest way to execute a stored procedure and map the results to a custom type when you are using a DbContext is probably by using the DbContext.Database.SqlQuery method:

    using (var context = new Entities())
    {
    IEnumerable results = context.Database.SqlQuery(“EXEC spGetInfo”);
    }

    You should still be able be use function imports if you are using the database first approach though.

    For any questions about Entity Framework in general, I recommend you to ask them in the official MSDN forum for ADO.NET Entity Framework and LINQ to Entities: http://social.msdn.microsoft.com/Forums/en-US/home?forum=adodotnetentityframework

  12. Harold Gomez says:

    Excellent!!

    Is the code available? I´m having some issues trying to create my own set of clases, and having this code will solve all my doubts.

    Thanks!!

  13. codeuniquely says:

    Stuck at separating the classes:

    When the model.tt file is included in the Domain Model a T4 Compile error is given at line1 column 1

    Error 78 Running transformation: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.IO.FileNotFoundException: Unable to locate file

    Server stack trace:
    at Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService.ResolvePath(String path)
    at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
    at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

    Exception rethrown at [0]:
    at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
    at Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService.ResolvePath(String path)
    — End of inner exception stack trace —
    at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
    at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at Microsoft.VisualStudio.TextTemplatingA78A0006661DE823CAEF3DF2E7508D448FB4A525144E921E76D15D2F77F4F9211A11C3424C471888F1732B6C4C4356A76057B9814B7B88A4A34492A8EAD69619.GeneratedTextTransformation.DynamicHost.ResolvePath(String path)
    at Microsoft.VisualStudio.TextTemplatingA78A0006661DE823CAEF3DF2E7508D448FB4A525144E921E76D15D2F77F4F9211A11C3424C471888F1732B6C4C4356A76057B9814B7B88A4A34492A8EAD69619.GeneratedTextTransformation.EdmMetadataLoader.CreateEdmItemCollection(String sourcePath)
    at Microsoft.VisualStudio.TextTemplatingA78A0006661DE823CAEF3DF2E7508D448FB4A525144E921E76D15D2F77F4F9211A11C3424C471888F1732B6C4C4356A76057B9814B7B88A4A34492A8EAD69619.GeneratedTextTransformation.TransformText() E:\Tangoe\Migrate\DomainModel\Model1.tt 1 1 DomainModel

  14. codeuniquely says:

    Hi,

    When i copy the model from the EF5 DAL project to the new DomainModel T4 generates a large number of errors
    starting with Line 1 and:

    I have changed the include to the edmx as you suggested in the article

    Error 78 Running transformation: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.IO.FileNotFoundException: Unable to locate file

    Server stack trace:
    at Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService.ResolvePath(String path)
    at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
    at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

    Exception rethrown at [0]:
    at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
    at Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService.ResolvePath(String path)
    — End of inner exception stack trace —
    at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
    at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at Microsoft.VisualStudio.TextTemplatingGenerated.TextTransformation.DynamicHost.ResolvePath(String path)
    at Microsoft.VisualStudio.TextTemplatingGenerated.TextTransformation.EdmMetadataLoader.CreateEdmItemCollection(String sourcePath)
    at Microsoft.VisualStudio.TextTemplating.Generated.TextTransformation.TransformText() E:\Migrate\DomainModel\Model1.tt 1 1 DomainModel

  15. Jagdish says:

    Make sure hostspecific=”true”

    by default it is false.

  16. Rohit Singh says:

    HI,I am new in edimx can you help me out to resolve this error “Unable to load the specified metadata resource.” thanks

  17. […] also found a very comprehensive article on how to implement a generic repository pattern with the Entity Framework, but it was unable to […]

  18. Vince. says:

    Hi nice article, but I’m not really sure I follow this. How can the repository be generic if it is tied to the entity class generated for to the repository that your using e.g. the GenericDataRepository class is referring to the Entities class in the implementation methods of the IGenericDataRepository interface. I thought it was suppose to be generic and an abstract class so that you could build your own repository and have this as the base and build the specific methods that you would need but most of the CRUD would already be in place?

  19. Hi Vince,

    The GenericDataRepository class is a generic class that implements the CRUD methods and serves as the base class for the specific repositories, DepartmentRepository and EmployeeRepository. I am not sure what you mean with “the GenericDataRepository class is referring to the Entities class”.

  20. Vince. says:

    Hi Magnus, thanks for the reply. What I meant was that the methods in the GenericDataRepository create an Entities object when it needs to query the DB. e.g.

    public virtual void Update(params T[] items)
    {
    using (var context = new Entities())
    {
    foreach (T item in items)
    {
    context.Entry(item).State = System.Data.EntityState.Modified;
    }
    context.SaveChanges();
    }
    }

    it is the class that was generated from EF Designer right? or maybe I’m misunderstanding on what this is suppose to accomplish. I taught it was suppose to be generic repositories where I have re-usuable code for any DB that I’m generating through the designer e.g. today I’m working with table1, and table 2 from DB 1 and I create a repositories for those using GenericDataRepository as the base class , now i want to build another repository with table 3, and table 4 from DB 2 for another application I wouldn’t have to rewrite the basic CRUD operations as they were implemented in the GenericDataRepository class which is the base class for the new repositories but I can’t see how GenericDataRepository can be a base class if the Entities class that it is referring to is the specific class that was created thru the EF designer for the DB and tables that you want to query.

  21. Yes, the Entities class was generated from the entity data model (EDM). The .edmx file that represents the EDM is an XML file that defines the conceptual model, the storage model, and the mapping between these. EF uses these mapping files to map entities and relationships in the conceptual model to the corresponding tables in the database.
    This means that whenever you want to make some changes to the model, e.g. include new tables, you have to update it. You can do this by right-click the .edmx file in the Model Browser window and select “Update Model from Database”.

    For more information about the mapping between objects and data and an overview of the EF, please refer to the following link: http://msdn.microsoft.com/en-us/library/bb399567.aspx

  22. Vince. says:

    Thanks Magnus for the clarification.

  23. Matt Ford says:

    Hi Magnus,

    Great article and a really good help when trying to create my own solution so thank you very much!

    I would love to hear about how you’d handle users concurrently editing the same object and how to avoid conflicts. Marking an object as Modified makes EF write every attribute back to the database when ideally we only want the attributes that have changed. This would not only perform better, but would solve concurrency issues stopping one editing user overwriting another’s changes.

    Thanks again!

  24. Ronny Carlansson says:

    Hi Magnus,

    Fantastic article! Got answers to a lot of questions I have had.

    Thanks!

  25. J says:

    At step 9 you reference the IEntity interface, but don’t define that interface until your discussion on persisting disconnected graphs. Perhaps a forward reference…? Reading top-down, I started looking for this interface in the EF.

  26. J says:

    Can you give some pointers on how to implement a lazy loading (or similar) scenario…? In my scenario, I have Clients with Plans with Accounts with Statements. Each statement has a binary column that stores a PDF associated with the statement and a list of transactions. I don’t want to bring down every PDF for every Statement if I query for a Client.

    For example, what if I just want a list of Clients for the top level of a TreeView and want to lazy load the sub nodes as they are expanded?

    Thoughts?

    Excellent blog, by the way. Thanks for that.

  27. Hi J,

    You have to be “connected” to be able to load anything, lazy or not. Since you are working in a disconnected environment here, the context that was used to fetch the client or account entities will no longer be around when the user of the client application expands the TreeView.

    You could choose to load all related entities upfront by using eager loading if you know that the client side will need them, or get the PDF files on demand by exposing a business layer method that returns the file contents based on some identifier of a transaction or statement. The latter alternative is probably the best option considering performance if you request a lot of entities with a lot of related binary files.

  28. J says:

    Right… I commented too quickly. I had read through the article but hadn’t analyzed the code. Once I looked at it I saw that “eager loading” is explicit rather than automatic. That’s all I really need. Just so I can request a list of Clients without it automatically bringing down the entire hierarchy.

    Now, after I populate my TreeView root with Clients and someone expands a node to see that particular Client’s Plans, I figure I can “attach” all those Plans to the existing Client object simply by adding them to Client POCO’s Plans collection. That’ll give me a full graph that I can use for updates and makes navigation through the hierarchy on the client pretty easy.

    I have learned a good deal about EF and Generics from this post. It’s good stuff. Thanks, again.

  29. J says:

    Magnus,

    What are you gaining with IBusinessLayer? Can you give me an example of where you’d have a use for that interface outside of the BusinessLayer class itself?

    Thanks.

  30. Interfaces let you separate the definition of objects from their implementation and make it easy to create loosely coupled software.

    In this case the implementation details of the business layer is hidden from the client and you can easily add another implementation of the business layer by simply creating another class that implements the IBusinessLayer interface.

  31. J says:

    I understand the general benefit of an interface. I’m just curious why it’s applied here other than just to conform to a model. An interface makes sense where you might have several different classes that would want to implement it along with some additional class specific stuff (your repository comes to mind). I suppose that if you wanted to replace the BusinessLayer class the interface might be a means to verify that you’ve implemented all the functionality… Anyway, that might just be a philosophical debate.

    Here’s a real question… (keeping in mind that I am now refactoring to incorporate the structure in this blog to get passed some issues I was having with maintaining dbContexts, etc…)

    I was using static classes for the BL stuff so that there was no need to instantiate a BL object every time you wanted to access data. In your BL, it seems you also instantiate an instance of each repo every time you instantiate a BL. Is there any performance concern with that? What if I have 20 or more entity types. Would I see a benefit to a static BL that only has to instantiate each repo once?

    In my case, I have a multi-tenant scenario. The user logs in and the BL caches some info about the logged-in user so that it can filter all future requests to data specific to that tenant. I could use static members for that bit, I suppose.

    So, I guess my question is, why not make use of static classes? (For one they can’t implement interfaces, which is how I ended up at the original question on why you had used the interface.) But would a static class, in this case, be more efficient?

    Thoughts?

  32. Ranjan says:

    Hi Magnus,
    Blog is really helpful to design architecture using EF. Thanks for sharing.

    I have one questions here.
    Why ‘IGenericDataRepository’ and ‘GenericDataRepository’ are derived from ‘IEntity’? It seems that there is functionality exteded from ‘IEntity’ interface.?

  33. Ranjan says:

    Hi J,
    Answer to your question of ‘Why not to use static classes’ is use of static classes meanse there is direct dependancy (coupling) between objects of Business layer and UI / Client.

    As Magnus has designed BL using interfaces ensures that system is build over the principle of loose coupling (DI) and you could impliment it easily by any IOC containers availables. This patterns ensures easy testability and maintanability.

    Let me correct Magnus if above details are not on right track.

  34. Hi Ranjan,

    The generic IGenericDataRepository interface doesn’t derive from the IEntity interface but the type parameter T is constrained to derive from the IEntity interface: http://msdn.microsoft.com/en-us/library/d5x73970.aspx

  35. Hi Mangus,
    Look here: IList GetList(Func where, params Expression<Func>[] navigationProperties)

    I think there should be Expression<Func> where – in this case “where” will be translated to SQL
    Also related to GetSingle

  36. Mangus, It would be nice if you extend this repository with sorting and paging support. Thank you

  37. Ranjan says:

    Hi Magnus,

    Sounds good.

    Thanks for quick updates.

  38. Hi Vitaliy,

    Yes, when using a Func<T, bool>> you are basically calling Enumerable.Where and the filtering is done in memory while using an Expression<Func<T bool>> will result in a call to the IQueryable.Where method.

    I answered a forum question regarding this a couple of months ago and should probably modify the Get methods in the sample code to use expressions: http://social.msdn.microsoft.com/Forums/en-US/6ec6ad27-2156-471b-8cb4-6007ec2f5297/code-first-linq-firstordefault-query-not-create-sql-where?forum=adodotnetentityframework

  39. J says:

    Magnus… In an attempt to make sure the user is getting the latest data, I added a refresh method to the repo/BL and call it before I display a details screen:

    public virtual void Refresh(params T[] items)
    {
    using (var context = new Entities())
    {
    DbSet dbSet = context.Set();

    foreach (T item in items)
    {
    dbSet.Add(item);
    foreach (DbEntityEntry entry in context.ChangeTracker.Entries())
    {
    IEntity entity = entry.Entity;
    entry.State = GetEntityState(entity.EntityState);
    }
    }

    context.ToObjectContext().Refresh(System.Data.Objects.RefreshMode.StoreWins, items);
    }
    }

    When I examine the code, it appears that all the data is actually getting refreshed. But, in the View, the bindings associated with the navigation properties break and no data (new or old) is displayed. How would you go about refreshing the data without breaking the bindings? (This appears to only be a problem if the data in the database has actually changed.)

  40. Alex says:

    Hi,

    If i have a third entity Adress, with also a one to many relationship between Adress and Employee, how can I change the GetAll() call to get the departments, their employee, and each employee’s adress ?

    (Sorry for my english)

  41. Pedro C. says:

    Hi, great Post..
    I don’t know if I am doing something wrong, but when I create the IGenericDataRepository , I got the following error:

    ” The type or namespace name ‘IEntity’ could not be found (are you missing a using directive or an assembly reference?) ”

    Should I include some other reference or “using” ?!
    best regards !

  42. Hi Pedro,

    The IEntity interface is a custom interface that defines a state property to let the entity objects track their own state. See the “Persisting disconnected graphs” section for more information.

  43. Niels says:

    Hi Magnus – Great post.
    I have a question about the eager loading, How to load deeper down.

    I.e. Departments have employees who have kids how would you load everything?

    repositotry.GetAll(e => e.Employees) would get all the departments with the employees, but how can you load in the kids as well from employee collection?

  44. J says:

    Magnus,

    Do you have any advice on how to manage graphs on the client side? I keep running into an issue where the object state manager complains about duplicate keys. In my schema Plans have Accounts which are associated with a Custodian On the client, for instance, I’ll load an account. On demand, I will load the custodian that account is associated with and populate the entity’s nav prop. If I load another account and then need its custodian, I end up with two different references to the same custodian. The if I try to update the graph, I end up with the conflict. (I tried using context.Entry, rather than dbSet.Add, but it didn’t help. Do I have to create a repository manager on the client to make sure I only ever use the same instance of a particular entity?

    Thoughts?

    Thanks.

    J

  45. Sadique says:

    If i use WCF service to connect UI(WPF) to server side where BL,DAL etc exists. how can i implement CRUD operations…..????, i dont have referece to any layer from UI other than i added service to UI.
    for more info please check part2 and 3 of the following link http://www.toplinestrategies.com/dotneters/net/wcf-entity-framework-and-n-tier-solutions-part-2/?lang=en

    plz help ..in crud over wcf…

  46. tedd says:

    Nice article Magnus. Just wondering, would not the custom property definitions ( i.e. EntityState {get;set;} )be overwritten everytime the Poco entities are regenerated? How do you stop that from happening?

  47. erizaldi says:

    Hi Magnus, great Article. I learn a lot from this. Thanks.

    Hi Tedd, I think POCO created partial class when generate entities. In this case, you can create the new partial entity class (with the same name) that contain other/additional properties such as EntityState {get; set;} or whatever. Is that correct Magnus?

  48. rbanning says:

    @erizaldi

    I did as you suggested – created partial classes to implement IEnity.

    One word to others – get the spelling right on your class name or you will be spending loads of time wondering why “there is no implicit reference conversion from ‘Department’ to ‘IEntity’ :=)

  49. @rbanning:
    Thanks man. I wound up tinkering with the T4 templates that EF uses to generate these entities so that on creation the entities inherit IEntity. Was worthwhile in the end.

  50. Hi

    this question is about DAL, imagine you separate POCO classes from your edmx in a Project. but now you need to “decorate” this classes for diferent needs like for example metadata for RIA services or validation for MVC4 project….
    how did you implement this without using partial classes, and having different projects for each need?

    Thanks


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s