Search code examples
c#asp.netasp.net-mvcentity-frameworkdto

Advice on my ASP.NET MVC, EF layer, and Automapper setup for a project


I'm trying to figure out the best approach to architecting this project. Basically, it's a "band" profile site. I'm using ASP.NET 4, EF, and Automapper (structuremap too, but that's not important). I'm running into performance issues and need advice on whether my approach is right or not (my guess is not). I'll focus on specific sections and provide stripped down examples.

I have a EntityFramework repository class that interacts directly onto the EF objects using LINQ:

[Pluggable("Repository")]
public class EntityDataRepository : IRepository
{
    static EntityDataRepository()
    {
        // other mappings removed
        // Data. objects are EF objects, mapping to my DTO classes
        Mapper.CreateMap<Data.Event, Models.EventModel>();
        Mapper.CreateMap<Data.Genre, Models.GenreModel>();
        Mapper.CreateMap<Data.Band, Models.BandModel>();
    }

    public IEnumerable<BandModel> GetBandsByUser(Guid userId)
    {
        using (var ctx = new DbContext())
        {
            var user = GetCurrentUserModel(ctx, userId);

            var efBands = from r in user.BandRelations
                            orderby r.Date
                            select r.Band;

            return Mapper.Map<IEnumerable<Data.Band>, IEnumerable<Models.BandModel>>(efBands);
        }
    }
}

Bands have genres and events. Note that it maps the EF objects to my DTO object, and returns a list of them. It acts as a proxy to enable my controllers to invoke methods on to obtain the data that it needs (actual logic altered to show what I need):

namespace OpenGrooves.Web.Areas.Edit.Controllers
{
    [Authorize]
    public class MyBandsController : BaseController
    {
        public ActionResult ShowBands()
        {
            IEnumerable<BandModel> bands = repository.GetBandsByUser(loggedUserGuid).First();

            return View(bands);
        }
    }
}

Finally, here's the BandModel class, which is mirroring the Band class entity in EF:

public class BandModel
{
    // fluff and scalar properties removed
    public IEnumerable<EventModel> Events { get; set; }
    public IEnumerable<GenreModel> Genres { get; set; }
}

Basically, am I doing this right? In my EF to DTO classes, the Band EF entity has navigational properties, such as Genres and Events. The problem is, during the mapping that takes place in automapper, these list properties are being populated, especially if one of my proxy methods returns a list of BandModels. It seems to be invoking the Genres and Event EF queries for each record, which is a major performance killer obviously (at least 2 queries for Events and Genres are ran for each BandModel object returned).

  • Is it OK practice to use EF objects directly in my controllers, possibly even used as models for views?
  • Is there something I need to change in my mappings to enable lazy loading for these navigational properties (events, genres off a BandModel object)?

Thanks!!


Solution

  • Is it OK practice to use EF objects directly in my controllers, possibly even used as models for views?

    Yes, Kinda.

    This answer is subjective and depends on how you view your separation of concerns. Most MVC developers, including me, swear on view models. It decouples your data or domain classes from the presentation layer. This is awesome.

    Some people don't like being awesome, including other languages and frameworks like every PHP MVC framework, Rails, and Django. Nobody can say these languages "do it wrong" but us .NET devs subscribe to a different paradigm.


    Your second question is strange you say "is there something to enable lazy loading" right after you say lazy loading is happening. Care to explain?

    Lazy loading is on by default in EF4.