2

I'm getting my data through to my app as an anonymous type to avoid selecting the entire row every time; just getting what I need.

Since I can't bind my GridView to an anonymous type (that I know of), I'm passing the anonymous type to a factory that builds the ViewModel and returns it so I have something to bind to.

What I was doing before implementing the factory is selecting the data into a new viewmodel and getting a list:

using (var db = new ApplicationDbContext())
{
    var timesheets = db.Timesheets.Where(x => x.StaffMember.Id == userId && !x.Deleted)
        .Select(x => new { x.Id, x.DateAdded, x.DateCompleted, x.Approved, x.Company.TradingName, x.StartTime, x.EndTime }).ToList();

    return timesheets.Select(x => new TimesheetListViewModel
    {
        Approved = x.Approved,
        CompanyName = x.TradingName,
        DateAdded = x.DateAdded,
        Completed = (x.DateCompleted.HasValue) ? DateTime.Parse(x.DateCompleted.ToString()) : DateTime.MinValue,
        Id = x.Id,
        StaffCanEdit = (x.EndTime == null),
        StartTime = TimeSpan.Parse(x.StartTime.ToString()),
        EndTime = (x.EndTime.HasValue) ? TimeSpan.Parse(x.EndTime.ToString()) : TimeSpan.MinValue
    }).ToList();
}

At this point, I think you'll agree, there is far too much parsing being done here to be viable in the service, so the factory implementation is intended to clear that work out of the service.

I've tried to do this 2 ways:

First way - passing the properties to the factory:

var factory = new TimesheetViewModelsFactory();
using (var db = new ApplicationDbContext())
{
    var timesheets = db.Timesheets.Where(x => x.StaffMember.Id == userId && !x.Deleted)
        .Select(x => new { x.Id, x.DateAdded, x.DateCompleted, x.Approved, x.Company.TradingName, x.StartTime, x.EndTime }).TOList();

    return timesheets.Select(x => factory.GetListViewModel(x.Id, x.DateAdded, x.DateCompleted, x.Approved, x.TradingName, x.StartTime, x.EndTime).ToList();
}

This had the problem that the function had no .ToList() method or such so wasn't viable and then I thought what if I just passed timesheets through?

Second way - passing the timesheet anonymous type to the factory:

var factory = new TimesheetViewModelsFactory();
using (var db = new ApplicationDbContext())
{
    var timesheets = db.Timesheets.Where(x => x.StaffMember.Id == userId && !x.Deleted)
        .Select(x => new { x.Id, x.DateAdded, x.DateCompleted, x.Approved, x.Company.TradingName, x.StartTime, x.EndTime }).TOList();

    return factory.GetListViewModel(timesheets);
}

At this point, I now have the following method generated in my factory from this call:

internal List<TimesheetListViewModel> GetListViewModel(List<object> timesheets)
{
    throw new NotImplementedException();
}

I don't know how to work with this...

Do I simply iterate through each item in timesheets and cast it to a Timesheet object, then map that to a view model?

Ortund
  • 8,095
  • 18
  • 71
  • 139
  • Try separating your query from mapping code so that you'd only select rows you want. I think it would also be good idea to create DTOs representig your data comming from DB otherwise you don't even have a type to cast to meaning you'll be left with some kind of reflection based mechaninsm wchich seems far too complex to achieve what you want to do. – user3455363 Mar 18 '19 at 12:22
  • You may also want to have a look at AutoMapper. It can map anonymous types, See [this](https://stackoverflow.com/a/10465897/4684493) answer for details. – Hintham Mar 18 '19 at 13:04
  • @Hintham I have to admit, I still haven't got even a basic understanding of how to use AutoMapper. – Ortund Mar 18 '19 at 14:22

0 Answers0