Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

The following code is for mapping a dataRecord to a class. I don't like this solution since it requires to duplicate the logic of mapping for each field in every method which access to the same table.

What do you think about? What about using automapper?

public IEnumerable<Model.Accounts.User> GetUsers(int IDUser)
{
    using (var sqlClient = CreateSqlManagerInstance("ListUser", CommandType.StoredProcedure))
    {
        sqlClient.AddParameterWithValue("IDUser", IDUser);
        return sqlClient.ExecuteResultSet().Select(
           dataRecord => new GModel.Accounts.User
           {
               IDUser = dataRecord.GetInt("IdUtente"),
               FirstName = dataRecord.GetString("Nome"),
               LastName = dataRecord.GetString("Cognome"),
               //[...]
           }).ToArray();
    }
}
share|improve this question
1  
Avoiding code duplication in mapping layer between dataRecord and and what ? –  Marc-Andre Mar 14 '14 at 16:53

2 Answers 2

up vote 3 down vote accepted

I believe the easiest way to avoid duplication each time you read from the database is to create a constructor which receives a DataRecord as a parameter, and does the heavy lifting:

public class User {

    public User() {}

    public User(DataRecord dataRecord) {
        IDUser = dataRecord.GetInt("IdUtente");
        FirstName = dataRecord.GetString("Nome");
        LastName = dataRecord.GetString("Cognome");
        //[...]
    }

    //...
}

And then:

public IEnumerable<Model.Accounts.User> GetUsers(int IDUser)
{
    using (var sqlClient = CreateSqlManagerInstance("ListUser", CommandType.StoredProcedure))
    {
        sqlClient.AddParameterWithValue("IDUser", IDUser);
        return sqlClient.ExecuteResultSet().Select(
           dataRecord => new GModel.Accounts.User(dataRecord)).ToArray();
    }
}

You could also use an automatic mapping library, but before you choose to do that, you might want to look at some O/R mapping library, like NHibernate for , which should replace the mapping in your code altogether.

share|improve this answer
    
What about using framework like AutoMapper? –  Revious Mar 14 '14 at 16:38
1  
see my edit about O/R mapping –  Uri Agassi Mar 14 '14 at 16:49

Instead of using a lambda to do the mapping, you can pass in a function reference. Now the same function is uses for everytime the class need to create a User from a DataRecord.

public GModel.Accounts.User mapRecord(DataRecord dataRecord) {
  // code
}

public IEnumerable<Model.Accounts.User> GetUsers(int IDUser)
{
    using (var sqlClient = CreateSqlManagerInstance("ListUser", CommandType.StoredProcedure))
    {
        sqlClient.AddParameterWithValue("IDUser", IDUser);
        return sqlClient.ExecuteResultSet().Select(mapRecord).ToArray();
    }
}
share|improve this answer
    
Is there a way to make mapping selective for only the field which are returned by the store? –  Revious Mar 14 '14 at 16:39
1  
@Revious: If each of your DataRecords does not have all the fields of a User, this will make a consistent mapping more complicated. However, you can always write the method so it checks if a field exists before setting the object property. You just have to be careful handing User instances to the rest of your code, as all the fields might not be initialized. –  unholysampler Mar 14 '14 at 16:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.