Entity Framework and Creating a Reusable Abstraction#

I am currently working on an open source project called MyCodeCamp with Sean Chambers, Fabio Honigmann, and Esteban Garcia.  We decided to use ASP.NET MVC and Entity Framework (EF).  Although I use SubSonic 2.2 and 3 beta at work, I thought this might be a good time to learn other ORM type frameworks for comparison. I have used LINQ To SQL and NHibernate a little also, but am not an expert by any means.  And since we want this project to be accessible to as many as possible, we thought Entity Framework would be a good choice seeing as Linq2Sql is getting folded into Entity Framework anyway.

So, I don’t really know how most people use EF, but coming from working on SubSonic 3, I have some habits that I would like to keep, particularly, using a Repository<T> like pattern.  After looking at all the code and classes I would have to write if I did the traditional, IClassRepository and ClassRepository, I decided to make Repository<T> work kind of like it does in SubSonic 3 with SubSonicRepository<T>.  This was not as easy as I thought.

First problem is when you want to update the model, you need to open up the .edmx file in the designer which sometimes does not open and you have to reboot Visual Studio.  And if you make major changes to your data model, you are better off deleting the file and recreating it.  Now I don’t think that would go over to well if you actually used it to do your mappings of data to entity models, but I am not using Entity Framework that way.  I think it was their intention to use it more of as a mapper, but I think I have found a much easier and scalable way of mapping data to domain objects by using AutoMapper.  We use AutoMapper at work with SubSonic 3 and we just love it.  I won’t go into everything it does, but it is by far the best project out there for mapping objects to other objects.

So here is an example of how I am getting an entity object, then mapping it to a domain object.

public class Repository<T> : IRepository<T>
    {
        private MyCodeCamp.Data.MyCodeCampEntities context;
        public Repository()
        {
            context = new MyCodeCamp.Data.MyCodeCampEntities();

        }

        public T GetById(Int32 id)
        {
            var tableName = typeof(T).Name;
            var key = new EntityKey("MyCodeCampEntities." + tableName, "Id", id);
            var r = (T)context.GetObjectByKey(key);

            return r;
        }
    }

Notice, since I am using T, I need to use reflection to get the Entity Name, or table name.  Then this data returns to a BaseService<TModel, T>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AutoMapper;
using MyCodeCamp.Data;

namespace MyCodeCamp.Domain.Services
{
     public abstract class BaseService<TModel, T>
        where TModel : new()
        where T : new()
    {
         public Repository<T> _repo;

         protected BaseService()
        {
            _repo = new Repository<T>();
            // Cache maps
            var tm = Mapper.FindTypeMapFor<T, TModel>();
            if (tm == null)
            {
                Mapper.CreateMap<T, TModel>();
            }

            tm = Mapper.FindTypeMapFor<TModel, T>();
            if (tm == null)
            {
                Mapper.CreateMap<TModel, T>();
            }
        }

         public virtual TModel GetById(Int32 id)
         {
             var item = _repo.GetById(id);
             var model = Map(item);
             return model;
         }

        public virtual TModel Map(T d)
        {
            return Mapper.Map<T, TModel>(d);
        }


    
    }
}

Now for the service that derives form the BaseService:

public class VenueService : BaseService<Model.Venue, Data.Venue>
    {
        public VenueService()
        {
           
        }
        
        public List<Model.Venue> GetByCity(string city)
        {
            var result = _repo.Find(v => v.City == city);
            var venues = result.ToList();
            var venueModels = Map(venues);
            return venueModels;
        }

        
    }

As you can see the Code is very clean and simple to read.  What is nice about going down this road with the AutoMapper is that mapping is completely automated and I don’t have to remap anything if I change properties or add them to the data model.  All I need to do is make sure the Property is on the domain model, then it will get mapped.  Also it will map by convention also, so if you have a Complex type as a property, like, Venue.Room.Name it would automatically map to a flattened dto like Venue.RoomName.  There are a ton of other conventions also, but you should go download AutoMapper and look at the tests to see all of the possibilities.

The next big issue I ran into was that the data was not getting updated when I would pass a detached object to the EF context.  Since I was creating the object that needed to get passed in outside of the ObjectContext scope, I needed to get the EF ObjectStateManager to recognize that the Entity Object had changed and to persist it.  I again had to use a little bit of reflection, but after I understood how EF handled things, it made more sense.  It was quite frustrating for a few hours trying to figure out why EF was not persisting updates and only inserts.  As you can see with the code below I needed to get the value of the Entity Key and the hydrate the entity object so that the ObjectStateManager knew that the data had been changed.

public int Update(T o)
       {
           var tableName = typeof(T).Name;

           // Need to get object out of ObjectStateManager, then set it so the dbcontext knows to persist changes
           var Id = GetPrimaryKeyValue(o);
           T currentObject = GetById(Id);
           currentObject = o;

           context.ApplyPropertyChanges(tableName, currentObject);

           return context.SaveChanges();
       }

       private int GetPrimaryKeyValue(T o)
       {
           int Id = 0;
           var properties = typeof(T).GetProperties();
           foreach (PropertyInfo p in properties)
           {
               if (string.Compare(p.Name, "Id", true) == 0)
               {
                   var r = p.GetValue(o, null).ToString();
                   Id = int.Parse(r);
                   break;
               }
           }
           return Id;
       }
All in all, I don’t mind EF for the Data Access Mapping, and the way it is currently abstracted in our project, it could easily be switched out for Linq To Sql, Subsonic, or any other ORM that uses LINQ to access its data.  I think the best way to use Data Mapping technologies in the future is control your own mapping by using tools such as AutoMapper so that you are not locked in to one way of getting your data out of your database. 
Monday, May 18, 2009 4:39:27 AM UTC #    Comments [540]  |  Trackback

 

A Day of Ajax in Tampa changed to 6/21/2007#

I guess there has been a double booking of the Microsoft room for the 20th, so we had to move it to the 21st.  I hope you all can still make it.  we will all be speaking at Tampa Code Camp also on July 14th, so try to catch us there if you can also.  I will be showing some Silverlight and Ajax stuff at Tampa Code Camp.

Sunday, June 17, 2007 7:44:57 AM UTC #    Comments [122]  |  Trackback

 

Jacksonville Code Camp#
I just got back from Jacksonville CodeCamp this weekend and was very impressed with how organized it was. My hats off to Dennis and Vinay along with the many volunteers that did such a good job with the Code Camp. If it wasn't for you guys, this would not be possible. I really like the people I meet in Jacksonville. It is always fun!
Tuesday, August 22, 2006 8:00:00 AM UTC #    Comments [51]  |  Trackback

 

Thanks to all from Tampa Code Camp#
Wow was that a fun code camp! We had a few hiccups during lunch (no food left for people late to line like me), but that was taken care of with pizzas later from VisualGov, thanks.

There were so many good people that i met and it was so cool to meet some of the new speakers that are brave enough speak here in Florida. We also had some great speakers from out of town who flew all the way into Tampa. We really did appreciate that.

So, to those who attended my session on advanced atlas controls, i am going to let you download the code samples that i demonstrated, but I have newer code that is more robust and takes advantage of other new features of the toolkit as of today. So once that code gets properly tested, i will post the changes here.
Tuesday, July 18, 2006 8:00:00 AM UTC #    Comments [70]  |  Trackback

 

Tampa Code Camp#
Ok, I just realized that I have not blogged in almost a month. So if I still have any readers, you may be interested in what my sessions are about at Tampa Code Camp if you have already signed up. We are completely full, and then some. I have been so busy working on a control for the atlas toolkit that mimics a balloon behavior similar to netflix and the many other things i do in my day and night jobs. I am doing two sessions tomorrow at Tampa Code Camp, one on Code generation and the ohter on how to create an atlas control. I am refactoring the balloon behavior again and am anxious to get it out there. In the code generation session I am going to show you how we bult tampa code camp using codesmith tools. I have fallen in love with that software. I don't think in sql anymore. Pretty cool.

See you there!
Friday, July 14, 2006 8:00:00 AM UTC #    Comments [59]  |  Trackback

 

Sorry to Orlando Code Camp#
Well when I got home from MIX06, the viruses were mixing at my home with my 3 kids. I thought I could avoid it, but this morning, it hit me like a brick. I won't get into to details. Lets just say its not a cold.

To make it up I will come and speak to the users group in Orlando sometime in the next few months on AJAX, Atlas and some other fun things I learned at MIX06.

I was really looking forward to seeing you all up in Orlando and look forward to seeing you in Tampa Code Camp this summer. I will talk to someone up in Orlando and see when would be a good time to speak to the users group up there.

Have a great day! Wish I was there and not in the bathroom!
Saturday, March 25, 2006 9:00:00 AM UTC #    Comments [83]  |  Trackback

 

Links for Fort Lauderdale Codecamp Sessions#
Here are the links to download the libraries I showed in the demos today.

My Ajax 12

Anthem.net

Atlas

Ajax.net


Have fun building ajax applications! Its easier than you think.
Saturday, February 04, 2006 10:00:00 AM UTC #    Comments [104]  |  Trackback

 

Fort Lauderdale Code Camp#
I will be doing two session in fort Lauderdale on Feb 4th, 2006 at the Code camp down there. I am very excited to learn many new things that are out there now a days. There is so much that is new and exciting that my mind is already overloaded. This will be a great time to learn from people that have real world experience and meet some cool people that also like to code late on Friday nights, like I am tonight.

Here is a link to my session information
http://64.139.141.119/speakers.aspx?#ZIMMERMANJIM

Also here is the link to the actual code camp even itself
http://www.fladotnet.com/codecamp

Hope to see you all there and for those that have never been to a superbowl party in Fort Lauderdale, you need to stick around the next day and hang out downtown. They block everything off and it becomes a street part with big screens. Lots of fun!
Thursday, January 19, 2006 10:00:00 AM UTC #    Comments [81]  |  Trackback

 

This one time at code camp#
This one time at code camp (Jacksonville), my laptop screen went out before my presentation. I ran into this cool guy named Mike who worked for a large insurance company and told him that I was nervous to drive my presentation from the wall and not my laptop screen so I would not be able to face the audience. Plus my presentation was mostly code, so it was going to be very hard to drive the screen from the wall and present at the same time.

Then I thought, hey do you have a crossover cable? He said yea, actually I do. Then I asked if I could borrow his laptop and set up a network connection and then remote desktop to my laptop which had all of the code on it. I asked Dave to see if they had a monitor that had mulitple video out and he want to look for one.

Meanwhile, Mike and I go up to an empty room and figure out the way to remote desktop into my laptop and then I drive the session through his laptop. We get it to work about 15 minutes before my session.

Thanks Mike for your help and being there at the right time. Funny how things work sometimes.

Anyway, I had a fun time in Jacksonville and am looking forward to going to Tallahassee Code camp on Sept 24th. I hope to see you all there.
Wednesday, September 14, 2005 8:00:00 AM UTC #    Comments [84]  |  Trackback

 

AJAX Now with ASP.NET Part 2 in Jacksonville#
I had a great time in Jacksonville this last weekend. I really enjoyed meeting some very smart people. It was also cool to meet the folks at MSN who were also very smart and enlightening. For those of you that saw my code demos you already know that I cannot post my code for the build a car because of contract reasons, but you can download the other samples that I showed. I will also be posting a few real world examples of the code I did show for build a car shortly, just not in its entirety(sp). For now you can download my other two demos below on my previous post.

I had a great time meeting you all!
Wednesday, August 31, 2005 8:00:00 AM UTC #    Comments [90]  |  Trackback

 

Tampa Code Camp Update#
I will be posting my code samples for AJAX for ASP.NET 2.0 tomorrow, on Sunday. I really enjoyed meeting new developers to challenge my brain and joke around beer objects at the dotnet pub club.
Sunday, July 17, 2005 8:00:00 AM UTC #    Comments [112]  |  Trackback

 

 

All content © 2012, Jim Zimmerman
Book
New Book
Links to me
On this page
Sponsors
Calendar
<February 2012>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910
Archives
Tags
Blogroll OPML
Technorati
Favorite Links
Disclaimer

Powered by: newtelligence dasBlog 1.9.6264.0

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Send mail to the author(s) E-mail