views:

3211

answers:

2

I am building a WPF application using the MVVM pattern. Our stack looks like this:

SQL Server 2008 -> Entity Framework

We use StructureMap for dependency injection to inject our DataFactory which essentially does the CRUD for our POCO business objects.

The ViewModels use the DataFactory for CRUD and the xaml is data bound to the properties in the POCO's.

The whole thing works great but the only thing I find to be somewhat of an annoyance is in the data factory. We copy each property from the EF Object to the POCO one on select and the reverse on update/insert.

Is there any way to automate this process like Fluent does for NHibernate but with the Entity Framework?

Here is a sample insert method in the data factory:

public void InsertCustomer(ref Manager.Model.Customer businessObject)
{
    var mgr = new Manager.Data.PersonData.PersonContext();

    var person = new Manager.Data.PersonData.Person();
    var customer = new Manager.Data.PersonData.Customer();

    customer.Comments = businessObject.Comments;
    customer.Company = businessObject.Company;
    customer.IsBusiness = businessObject.IsBusiness;
    customer.IsCompleted = businessObject.IsCompleted;
    customer.ModifiedBy = "someone";
    customer.ModifiedOn = DateTime.Now;
    customer.CreatedBy = "someone";
    customer.CreatedOn = DateTime.Now;

    person.Customer.Add(customer);
    person.FirstName = businessObject.FirstName;
    person.LastName = businessObject.LastName;
    person.Birthday = businessObject.Birthday;
    person.CreatedBy = "someone";
    person.CreatedOn = DateTime.Now;
    person.Gender = businessObject.Gender;
    person.MiddleInitial = businessObject.MiddleInitial;
    person.ModifiedBy = "someone";
    person.ModifiedOn = DateTime.Now;
    person.Nickname = businessObject.Nickname;
    person.Picture = "";
    person.Suffix = businessObject.Suffix;
    person.Title = businessObject.Title;

    mgr.AddToPeople(person);
    mgr.SaveChanges();
}

It would be nice to declare some class, like Fluent does it:

public class CatMap : ClassMap<Cat>  
{  
  public CatMap()  
  {  
    Id(x => x.Id);  
    Map(x => x.Name)  
      .WithLengthOf(16)  
      .Not.Nullable();  
    Map(x => x.Sex);  
    References(x => x.Mate);  
    HasMany(x => x.Kittens);  
  }  
}

Finally my insert method would look like this:

public void InsertCustomer(ref Manager.Model.Customer businessObject)
{
    var mgr = new Manager.Data.PersonData.PersonContext();

    var person = new Manager.Data.PersonData.Person();
    var customer = new Manager.Data.PersonData.Customer();

    Something.Map(person, businessObject);
    Something.Map(customer, businessObject);  

    person.Customer.Add(customer);

    mgr.AddToPeople(newCustomer);
    mgr.SaveChanges();
}

Essentially I would eliminate the code to move data from the business object to the entity frame work object it would be done once in the mapping class and would not have to be repeated for each method.

Thanks!

A: 

Although I'm not aware of a data mapper that does what you want for EF, it isn't hard to write one. Also since defining the mappings is most of the work, it really isn't any harder than using the fluent interface mappings that you listed. You just create a Mapper class that has multiple map functions, each of which contains your mapping logic.

One thought that might be interesting is to make your map functions extension methods. You would still create a Mapper class, but each of the map methods would look like

    public static Person MapToPerson(this Manager.Model.Customer bizObject)
    {
        Person person = new Person();
        // mapping logic
        return person;
    }

Since the MapToPerson method is an extension method, and not really a method on your bizObject class, you're not breaking the POCO. But, because of the syntactic sugar of the extension method, your InsertCustomer method could have code like this:

    Customer customer = bizObject.MapToCustomer();
    Person person = bizObject.MapToPerson();
Rudy Lacovara
+9  A: 

You can try Automapper, works for me.

http://www.codeplex.com/AutoMapper

mxmissile