Entity Framework Core: Custom Linq methods for querying view models from DbContext

.net-core c# entity-framework-core linq


I am developing a .NET Core web API using .NET Core 2.0 and Entity Framework 2.0. The project and especially the amount of view models keep growing and the complexity becomes more intense (more nested models). The main point for my question is that the view models share a lot of sub models.

And I bet I don't use the correct keywords for googling because I can't find what I want to know.

Currently I query and map them (according to some defined logic) directly via the DbContext (each time aka for each view model). For example:

List<MyViewModel1> items = await MyDbContext.MyDbModel1
  .Where(dbm1 => dbm1.SomeValue > 10)
        dbm1 => new MyViewModel1 
            ValueName = dbm1.SomeValue,
            NestedModel1 = new NestedViewModel1 
               SomeValue1 = dbm1.OtherTableModel1.Value1,
               SomeValue2 = dbm1.OtherTableModel1.Value2
            NestedModel2 = (!dbm1.OtherTableModel2Id.HasValue) ? null :
                  new NestedViewModel2 
                     SomeCalculatedValue = dbm1.OtherTableModel2.Value1 + dbm1.OtherTableModel2.Value2,
                     SomeOtherValue = dbm1.OtherTableModel2.Value3

Now the problem is: NestedViewModel2 (the one with the calculation) is attached to multiple view models and so far I write this calculation every time in the same way as above (for MyViewModel1, MyViewModel2, MyViewModel3,...). And as it is, requirements change regulary. And each time the requirements change I have to spot all places in my growing code and fix the calculation on multiple places.

That approach does not follow DRY (don't repeat yourself).

But I can't find information if it is possible (and how) to write some custom linq extension methods (which entity framework will understand for the linq to SQL conversion) like:

  • SelectViewModel1WithValueGreaterThan(this DbSet, int greaterThan)
  • SelectViewModel2List(this DbSet)
  • SelectViewModel3Details(this DbSet)

and especially have the Nested Models select in one place (that can get called from the above methods).

  • SelectNestedModel1(???)
  • SelectNestedModel2(???)

Any hints for me how to pack those queries into custom linq extension methods so the code follows the DRY principle and can be reused?

5/15/2018 7:20:21 AM

Accepted Answer

You should take a look at a mapping framework to map the DB Entities to the ViewModels. For example, we are using Automapper to achieve this.

This allows you to define the mappings centrally and reuse them. This should simplify most of the code, because the logic you want to refactor is in the select part of the query.

MappingConfig.CreateMap<MyDbModel1, MyViewModel1>()
    .ForMember(vm => vm.ValueName, o => o.MapFrom(ent => ent.SomeValue))
    .ForMember(vm => vm.NestedModel1, o => o.MapFrom(ent => ent.OtherTableModel1));

MappingConfig.CreateMap<OtherTableModel1, NestedViewModel1>()
    .ForMember(vm => vm.SomeValue1 , o => o.MapFrom(ent => ent.Value1))
    .ForMember(vm => vm.SomeValue2 , o => o.MapFrom(ent => ent.Value2));

var items = Mapper.Map<MyViewModel1[]>(MyDbContext.MyDbModel1.Where(dbm1 => dbm1.SomeValue > 10));
5/15/2018 9:02:39 AM

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow