Sony Arouje Blog

a programmer's log

Posts Tagged ‘Entity framework

Entity Framework Vs NHibernate

with 2 comments

I worked on EF POCO model for some times and I come across with several stopovers. EF doesn’t have a very good error reporting, it will just throw some error and we need to run pillar to post to find out why on earth we are getting this error. Another issue is working in disconnected mode, I will explain in detail later in this post. For testing I used EF CTP5, hopefully things might have improved in the latest release.

After dating with EF for quiet some time, I realized that EF is not matured enough to hang around with, it’s still evolving and need time. I thought I need to look around and see any other beautiful and healthy ORM’s around. Yes I do aware of NHibernate a powerful ORM in the market for quiet a long period. So I decided to see in depth. I decided to write a small app to compare both ORM’s. For my comparison I used FluentNHibernate, I like to map my entities to table using code rather than an xml.

I haven’t completed the comparison yet. One of the important focus of my test is how CRUD operation works in disconnected model. In connected model the context can keep track of the changes and do the necessary Create/Update/Delete operation without much issue. So my test app have a WCF service to supply data to presentation layer.

First Test

The presentation layer issue a search request and get an author object from the WCF service, make some changes to author data and send it back to service for persisting it.

Entity Framework: Presentation layer get author object, did some changes to First Name. Sent the modified object to Service for persisting. In the persistence layer attached the author object to ObjectContext and called SaveChanges(). But nothing happened, EF couldn’t recognize the changes made to the object and didn’t persist the changes.

NHibernate: Presentation layer get author object, did some changes to First Name. Sent the modified object to Service for persisting. In the persistence layer make a call to SaveOrUpdate() of Session object with the modified entity. I could see that the changes get persisted to the db.

Test Summary

In my first test I could see that update operation in disconnected  mode is pretty easy in NHibernate than EF. I am not sure whether am doing some thing wrong in EF thus it’s not persisting. But from a devs stand point we really don’t want to do much stuffs with an ORM to persist any changes. It’s ORM’s headache to figure out whether the entity state is dirty or not, if dirty then update it.

After this small test I feel like I need to embrace NHibernate as my ORM. Also one of the good feature of NHibernate is it’s error reporting. NH will report error with sql statement it issued to db, it will be helpful for a dev to analyze the error and take necessary actions.

EF might be strong in Autogenerated code, with EDMX, blah, blah. But not yet matured enough to support POCO model. In my point of view NHibernate is the right ORM to choose in comparison with Entity Framework, if you are serious in POCO model.

Note: NHibernate uses lazy loading extensively and you may have some trouble in WCF side while serializing it. It’s advisable to use DTO to transfer data between layers. Trent Foley have a nice post to explain how to perform eager loading with NHibernate.

This is just an initial test and I will move forward to test different scenarios. If I get time I will post the results in future posts.

Overview of Test Application

The test application consist of Presention layer (Winform), WCF service, Domain model and Persistence layer. The service layer and the persistence layer is loosely coupled. At any point of time Service layer doesn’t know to whom he is interacting, it can be EF repository instance or NH instance, I achieved it by Caste Windsor IOC. This loosely coupled approach help me to compare both ORM without any single code change rather with a xml configuration change.

For the test app I used Pubs database. One of domain entity is shown below.

namespace ORM.Domain
{
    [DataContract]
    public class Author
    {
        [DataMember]
        public virtual string Id { get; private set; }
        [DataMember]
        public virtual string LastName { get; set; }
        [DataMember]
        public virtual string FirstName { get; set; }
        [DataMember]
        public virtual string Phone { get; set; }
        [DataMember]
        public virtual string Address { get; set; }
        [DataMember]
        public virtual IList<Titles> TitlesAuthored { get; set; }
        public virtual bool Contract { get; set; }

        public Author()
        {
            this.TitlesAuthored = new List<Titles>();
        }
        public virtual void AddTitles(Titles titles)
        {
            this.TitlesAuthored.Add(titles);
            titles.Authors.Add(this);
        }
    }

It’s just a anemic entity without much responsibility. Anyway my focus is not in DDD, so just bare with my entity structure.

Now I need to map my entity to Author table. I used fluent API’s of the ORM to do the mapping.

Entity Framework Mapping

public class AuthorConfiguration:EntityTypeConfiguration<Author>
{
    public AuthorConfiguration()
    {
        HasKey(a => a.Id);
        HasMany(a => a.TitlesAuthored);
        Property(a => a.Id).HasColumnName("au_id");
        Property(a => a.Address).HasColumnName("address");
        Property(a => a.FirstName).HasColumnName("au_fname");
        Property(a => a.LastName).HasColumnName("au_lname");
        Property(a => a.Phone).HasColumnName("phone");
        Property(a => a.Contract).HasColumnName("contract");
        ToTable("dbo.authors");
    }
}

FluentHibernate Mapping

public class AuthorMap:ClassMap<Author>
{
    public AuthorMap()
    {
        Id(x => x.Id,"au_id");
        Map(x => x.LastName, "au_lname");
        Map(x => x.FirstName, "au_fname");
        Map(x => x.Address, "address");
        Map(x => x.Phone, "phone");
        Map(x => x.Contract, "contract");
        HasManyToMany(t => t.TitlesAuthored).Cascade.All().Table("titleauthor")
                           .ChildKeyColumn("title_id")
                           .ParentKeyColumn("au_id");Table("dbo.authors");
    }
}

What ever I posted here is just my findings. Don’t consider this as a benchmark. You better consider your scenarios and do a small tracer and find out which suites your requirement. Pay careful attention before deciding on any ORM else you will suffer later.

I think it’s better to stop here, you all can look into my source code for more details. I uploaded my test application to Sky drive, if interested pls have a look at it.

Download Source code

Written by Sony Arouje

May 26, 2011 at 7:48 pm

Generic Entity Framework Repository with Eager Loading

with 7 comments

In this post am going to explain how we can write Generic repository for Entity framework. The implementation is based on the Repository pattern. Inspired by one of the blog by hibernatingrhinos 

Below code explains the Interface I used for creating the repository

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Generic.Repository.Repository
{
    public interface IRepository
    {
        IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class;
        IList<TEntity> GetAll<TEntity>() where TEntity : class;
        IList<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class;
        void Add<TEntity>(TEntity entity) where TEntity : class;
        void Attach<TEntity>(TEntity entity) where TEntity : class;
        void SaveChanges();
        bool EnableEagerLoading { get; set; }
    }
}

I only included only limited functionality to this Interface. You can extend the interface to add more functionality. Let’s see the implementation

using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Reflection;
namespace Generic.Repository.Repository
{
    public class GenericRepository:IRepository
    {
        string _connectionString = string.Empty;
        public GenericRepository(string connection)
        {
            _connectionString = connection;
        }
        #region Private methods
        private GenericContext _context = null;
        private GenericContext Context
        {
            get
            {
                if (_context == null)
                {
                    _context = GenericContext.GetContext(_connectionString);
                    _context.ContextOptions.LazyLoadingEnabled = false;
                }
                return _context;
            }
        }
        private IList<TEntity> LoadNavigationFields<TEntity>(IList<TEntity> entities) where TEntity : class
        {
            foreach (TEntity entity in entities)
            {
                PerformEagerLoading<TEntity>(entity, this.Context);
            }
            return entities;
        }
        private TEntity LoadNavigationFields<TEntity>(TEntity entity) where TEntity : class
        {
            PerformEagerLoading<TEntity>(entity, this.Context);
            return entity;
        }
        private void PerformEagerLoading<TEntity>(TEntity entity, ObjectContext context) where TEntity : class
        {
            PropertyInfo[] properties = typeof(TEntity).GetProperties();
            foreach (PropertyInfo property in properties)
            {
                object[] keys = property.GetCustomAttributes(typeof(NavigationFieldAttribute), true);
                if (keys.Length > 0)
                {
                    context.LoadProperty(entity, property.Name);
                }
            }
        }
        #endregion

        #region Generic Repository methods
        public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
        {
            return this.Context.CreateGenericObjectSet<TEntity>();
        }

        public IList<TEntity> GetAll<TEntity>() where TEntity : class
        {
            IList<TEntity> entities = this.GetQuery<TEntity>().AsEnumerable<TEntity>().ToList();
            if (this._enableEagerLoading == false)
            {
                return entities;
            }
            else
            {
                return this.LoadNavigationFields<TEntity>(entities);
            }
        }

        public IList<TEntity> Find<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            IList<TEntity> entities = this.GetQuery<TEntity>().Where(criteria).ToList();
            if (this._enableEagerLoading == false)
            {
                return entities;
            }
            else
            {
                return this.LoadNavigationFields<TEntity>(entities);
            }
        }

        public void Add<TEntity>(TEntity entity) where TEntity : class
        {
            this.Context.CreateGenericObjectSet<TEntity>().AddObject(entity);
        }
        public void Attach<TEntity>(TEntity entity) where TEntity : class
        {
            this.Context.CreateGenericObjectSet<TEntity>().Attach(entity);
        }
        public void SaveChanges()
        {
            this.Context.SaveChanges();
        }

        bool _enableEagerLoading = false;
        public bool EnableEagerLoading
        {
            get { return _enableEagerLoading; }
            set { _enableEagerLoading = value; }
        }
        #endregion
    }
}

The above implementation can be used in most of the CRUD operations. If you have any specific logic for your repository then you can extend it by implementing the IRepository interface. Most of the functionality doesn’t required much explanation except PerformEagerLoading().

Normally we load related entities using LoadProperty in the context or use Include in the Linq query. Both approach wont work here in generic approach as we do not know the properties to do this. I searched a lot to achieve eager loading in a generic mode. But nothing worked then thought of implementing one myself. I haven’t verified the performance of this approach but worked well for my scenario.

The approach I come with is, decorate the related entities with an attribute and use the reflection and iterate through the entity and load it using LoadProperty of context object. Below code will explain my approach.

private void PerformEagerLoading<TEntity>(TEntity entity, ObjectContext context) where TEntity : class
{
    PropertyInfo[] properties = typeof(TEntity).GetProperties();
    foreach (PropertyInfo property in properties)
    {
        object[] keys = property.GetCustomAttributes(typeof(NavigationFieldAttribute), true);
        if (keys.Length > 0)
        {
            context.LoadProperty(entity, property.Name);
        }
    }
}

 

NavigationFieldAttribute is a new attribute inherited from System.Attribute. You can see the implementation in my source code. For the implementation I used the same db model explained in my previous post.

Let’s write a test to verify our GenericRepository

string connectionString = "Data Source=PROLAPE00700\\SQLserver;Initial Catalog=ImagePublisher;User ID=sony;PWD=sony;MultipleActiveResultSets=True;";

[TestMethod()]
public void GetAllTest()
{
    IRepository genericRepository = new GenericRepository(connectionString);
    genericRepository.EnableEagerLoading = true;
    IList<User> users = genericRepository.GetAll<User>();
    Assert.AreNotEqual(0, users.Count);
}

[TestMethod]
public void FindTest()
{
    IRepository genericRepository = new GenericRepository(connectionString);
    genericRepository.EnableEagerLoading = true;
    IList<User> users = genericRepository.Find<User>(u => u.UserID == 1);
    User user = users[0];
    Assert.AreNotEqual(0, user.UserRoles.Count);
}

 

You can understand the EagerLoading functionality by setting false to EnableEagerLoading  in the FindTest above. If we do so the test will fail as it wont load User.UserRoles.

The advantage of this generic approach is we don’t want to create Repository object for each entity if you want to fetch a different entity in the same function. For e.g

IList<User> users=genericRepository.GetAll<Users>();

IList<Role> roles=genericRepository.GetAll<Role>();

Download the source code

Written by Sony Arouje

October 15, 2010 at 5:20 pm

Follow

Get every new post delivered to your Inbox.

Join 161 other followers

%d bloggers like this: