We have to use data transfer objects for many of our tables as they are very big and many columns aren't useful for the context I'm working.
To get the best performance I cannot read the complete database entities and covert it to dtos afterwards. Therefore I created a linq extension method to convert it to dtos before executing the query.
Call of extension method:
db.MyTable.Select(...).ToDto().ToList();
My extension method:
public static IQueryable<MyTableDTO> ToDto(this IQueryable<MyTable> query)
{
return query.Select(x => new MyTableDTO
{
ID = x.ID,
Name = x.Name
});
}
Is this a feasable solution or are there better practises to do that?
Second question: There aren't only IQueryable< MyTable > objects which needs to be transformed to dtos, also MyTable objects have to be transformed. I created an extension method for MyTable class:
public static MyTableDto ToDto (this MyTable x)
{
return new MyTableDto
{
ID = x.ID,
Name = x.Name
};
}
Why can't I use this function in my first ToDto function? Like:
public static IQueryable<MyTableDTO> ToDto(this IQueryable<MyTable> query)
{
return query.Select(x => x.ToDto());
}
UPDATE
A further question because of the research below. There are also cases where we want to return only a minimum of fields for high performance issues.
It is possible to create a repository class where you can define a parameter to pass a Func with the fields which should be returned by the query (as described below). Then it is possible to create a class (MyServiceClass in the example below) where you can call the same repository method with for different return entities. But is that a good practise or what would be a better solution for it?
public class MyTableRepository<T>
{
public List<T> GetMyTable(String search1, String search2, Func<MyTable, T> selectExp)
{
using(var db = new Context())
{
return db.MyTable.Where(x => x.A == search1 ...).Select(selectExp).ToList();
}
}
}
public class MyServiceClass
{
public List<MyTableEntitySimple> GetMyTableEntitySimple(String search1...)
{
MyTableRepository<MyTableEntitySimple> rep = new ...
return rep.GetMyTable(search1, ToMyTableEntitySimple);
}
public List<MyTableEntity> GetMyTableEntity(String search1...)
{
MyTableRepository<MyTableEntity> rep = new ...
return rep.GetMyTable(search1, ToMyTableEntity);
}
Func<MyTable, MyTableEntitySimple) ToMyTableEntitySimple = x => new MyTableEntitySimple
{
ID = x.ID,
Name = x.Name
};
Func<MyTable, MyTableEntity) ToMyTableEntity = x => new MyTableEntitySimple
{
ID = x.ID,
Name = x.Name,
Field3 = x.Field3,
Field4 = x.Field4,
...
};
}