0

I have two tables (lists): customers and sales that have an one-to-many relationship. I'm trying to create an automap that results in a list populated with CustomerSalesDto. For every Sale object a new CustomerSalesDto should be created with the Sale information and some of the information from the Customer who made the sale.

Can this be done with Automapping and how would I accomplish this?

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

public class Sale
{
    public int Id { get; set; }
    public double Price { get; set; }
    public DateTime Date { get; set; }
    public int CustomarId { get; set;} // Id from Customer who made a sale.
}

public class CustomerSalesDto
{
    public double Price { get; set; } // from Sale
    public DateTime Date { get; set; } // from Sale
    public string Name { get; set; } // from Customer
    public string Email { get; set; } // from Customer
}
Sam
  • 1,303
  • 3
  • 23
  • 41
  • If `Sale` had a property of type `Customer` fully populated then yes it would be possible. – Ric Sep 28 '15 at 14:16
  • Any work around if the type stays as an int? I'm using a framework that automatically injects the Customer id into the database when he makes the sale (not the object). – Sam Sep 28 '15 at 14:21
  • Do you use entity-framework or are you doing this manually? how do you populate a `Sale` object? – Ric Sep 28 '15 at 14:22
  • A sale is populated using a service and the repository pattern (entity framework within). In the same service as the "CreateSale()" function should be another function "GetSales()" where all the sales are stored with the matching user information in a list of DTOs. – Sam Sep 28 '15 at 14:26
  • TBH a `Sale` has an associated `Customer` so the way you could model this is by adding an additional property to `Sale` - otherwise to create your `CustomerSalesDto` you would need to access the repository to get sale and customer data - but how do you know from an `CustomerSalesDto` who the customer is and what the sale was?? (there are no id's in the class) – Ric Sep 28 '15 at 14:29
  • The CustomerSalesDto is only used in the View to populate a list with rows of all the sales. Is does not have a CRUD functionality and there is no need to keep track of more information about the original sale and user. I could add additional user-information properties to the sale model but this would result in data redundancy. – Sam Sep 28 '15 at 14:37

1 Answers1

0

You can do something like this:

First create a map from Tuple<Sale, Customer> to CustomerSalesDto like this:

AutoMapper.Mapper.CreateMap<Tuple<Sale, Customer>, CustomerSalesDto>()
    .ForMember(t => t.Name, m => m.MapFrom(f => f.Item2.Name))
    .ForMember(t => t.Email, m => m.MapFrom(f => f.Item2.Email))
    .ForMember(t => t.Date, m => m.MapFrom(f => f.Item1.Date))
    .ForMember(t => t.Price, m => m.MapFrom(f => f.Item1.Price));

Then you can create a method to match each sale with the corresponding customer and then use AutoMapper to create a list of CustomerSalesDto objects like this:

public List<CustomerSalesDto> Convert(List<Sale> sales, List<Customer> customers)
{
    List<CustomerSalesDto> result = new List<CustomerSalesDto>();

    Dictionary<int, Customer> customer_dictionary = customers.ToDictionary(x => x.Id); //This is done to speed things up

    foreach (Sale sale in sales)
    {
        if(!customer_dictionary.ContainsKey(sale.CustomarId))
            throw new Exception("Could not find the customer");

        Customer customer = customer_dictionary[sale.CustomarId];

        result.Add(AutoMapper.Mapper.Map<CustomerSalesDto>(new Tuple<Sale, Customer>(sale , customer)));
    }

    return result;
}
Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62