This project has moved. For the latest updates, please go here.

Map result row to a business class

Oct 27, 2013 at 6:49 PM
I was wondering if it's possible to use the mapping to classes such as this:
db.ExecuteReader<MyBusiness1>(GetProcedure("READ_TEST_DATA3"),
parameters =>
{
    parameters.Add("inAs_Of_Date", DateTime.Today);
},
map =>
{
    map.Add("SEC_ID", t => t.Id);
    map.Add("MARKET_VALUE", t => t.MarketValue);
    map.Add("CLOSE_DATE", t => t.CloseDate);
    map.Add("CLOSE_DATE", t => t.Person.FirstName);
    map.Add("CLOSE_DATE", t => t.Person.LastName);
    map.Add("CLOSE_DATE", t => t.Person.Age);
},
myBusiness1 =>
{
    myBusiness1List.Add(myBusiness1);
});
When I try a mapping like that (notice the Person class in my model) I get the following error:

<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>Object does not match target type.</ExceptionMessage>
<ExceptionType>System.Reflection.TargetException</ExceptionType>
<StackTrace>
at System.Web.Http.ApiController.<InvokeActionWithExceptionFilters>d__1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()
</StackTrace>
</Error>
Coordinator
Nov 19, 2013 at 11:52 PM
Edited Nov 19, 2013 at 11:56 PM
  • The last one mapping map.Add("CLOSE_DATE", t => t.Person.Age); is not supported, because a DateTime value cannot get to any numeric type. Refer to DateTime.IConvertible.ToInt16 or ToInt32.
  • map.Add("CLOSE_DATE", t => t.Person.LastName); and map.Add("CLOSE_DATE", t => t.Person.FirstName); These two are mapping a DateTime value to string type, they do work although they look no practical purpose.
  • The first three mapping map.Add("SEC_ID", t => t.Id); map.Add("MARKET_VALUE", t => t.MarketValue); map.Add("CLOSE_DATE", t => t.CloseDate); are supported by ADO.NET data provider straightforwardly.
Nov 20, 2013 at 12:04 AM
Edited Nov 20, 2013 at 12:05 AM
Sorry, I wasn't clear on what I was trying to achieve. I was looking for a way to populate a object using your Example 3 (map every result row to a business class by specified column-property mappings) when the class has a structure like below:
db.ExecuteReader<MyBusiness1>(GetProcedure("READ_TEST_DATA3"),
parameters =>
{
    parameters.Add("Id", 2);
},
map =>
{
    map.Add("ProgramId", t => t.Id);
    map.Add("ProgramName", t => t.Name);
    map.Add("SchoolId", t => t.School.Id);
    map.Add("SchoolName", t => t.School.Name);
},
programItem=>
{
    programList.Add(programItem);
});
I ended up going with Example 1 (single result set) to get the result I was looking for:
db.ExecuteReader(GetProcedure("READ_TEST_DATA1"),
parameters =>
{
    parameters.Add("Id", 2);
 }, 
row =>
{
P.Id = row.Field<type>("ProgramId");
P.Name = row.Field<type>("ProgramName");
P.School.Id = row.Field<type>("SchoolID");
P.School.Name = row.Field<type>("SchoolName");

});
Thanks for the response, this library has been really helpful and wish I discovered it sooner just what I need for smaller projects.
Coordinator
Sep 16, 2014 at 9:10 PM
Edited Sep 16, 2014 at 9:51 PM
Deep (nested) properties or fields are already supported. Please use the latest version via NuGet.

Notes:
To allow automap a database column to a deep Properties or Fields in .Net, please make sure that:
  1. All nested properties or fields run through in middle levels must be:
    • reference types (class or interface) only, struct is not supported;
    • have public parameterless constructor (or by default);
    • both read and write accessibility
    for your example,
      map.Add("SchoolId", t => t.School.Id);
    
    The nested property School in MyBusiness1 class must also be a class with a public parameterless (or default) constructor, and include both a get and a set accessor.
    
  2. The end property or field must be:
    • a value type or string type
    • both read and write accessibility
    for your example,
      map.Add("SchoolId", t => t.School.Id);
    
    The end property Id in MyBusiness1 class must be value type (e.g. int) or string, with both a get and a set accessor.
    
  3. There is no limit to the number of how many levels through the path from the root class object to the end property or field.
Hope this will help.

Thanks again,
Marked as answer by tszafran on 10/13/2014 at 7:36 PM
Oct 14, 2014 at 2:49 AM
Thanks for the update! Great library.