Reputation: 1266
I have created a class called DataResponse
that has more than 40 public fields. The class DataResponse
has the same number of fields and type as what's in my database DataRepoes
(let's assume that).
Is there a way at all to do something like linq below where I create list of objects and automatically the fields are assigned to DataResponse
from what's in the DB? Otherwise I have to spell out each and every those 40 fields and assign them manually when I new up DataResponse class. Thanks
List<Classes.DataResponse> res = (from rx in con.DataRepoes
where iaccess.Contains(rx.STOREID)
select new Classes.DataResponse).ToList<Classes.DataResponse>();
Upvotes: 0
Views: 665
Reputation: 205669
If you don't need the flexibility provided by AutoMapper or don't want using a third party library, you can use the following simplified custom extension method:
public static class QueryableExtensions
{
public static IQueryable<TResult> SelectTo<TResult>(this IQueryable source)
{
var sourceType = source.ElementType;
var resultType = typeof(TResult);
var parameter = Expression.Parameter(sourceType, "x");
var bindings =
from rm in resultType.GetProperties().Concat<MemberInfo>(resultType.GetFields())
join sm in sourceType.GetProperties().Concat<MemberInfo>(sourceType.GetFields())
on rm.Name equals sm.Name
select Expression.Bind(rm, Expression.MakeMemberAccess(parameter, sm));
var body = Expression.MemberInit(Expression.New(resultType), bindings);
return source.Provider.CreateQuery<TResult>(Expression.Call(
typeof(Queryable), "Select", new[] { sourceType, resultType },
source.Expression, Expression.Quote(Expression.Lambda(body, parameter))));
}
}
It will try to select all the properties/fields that match by name. Will fail if matched property/field types differ.
Sample usage:
Method syntax
var res = con.DataRepoes
.Where(rx => iaccess.Contains(rx.STOREID))
.SelectTo<Classes.DataResponse>()
.ToList();
Query syntax
var res =
(from rx in con.DataRepoes
where iaccess.Contains(rx.STOREID)
select rx)
.SelectTo<Classes.DataResponse>()
.ToList();
Upvotes: 1
Reputation: 2310
You can use Automapper Queryable Extensions for that.
Assuming the fields in Classes.DataResponse
have the same names as the ones in DataRepoes
you can then, do:
// During your application bootstrap, configure AutoMapper to create a map between the two types
Mapper.Initialize(cfg => cfg.CreateMap<DataRepoes, Classes.DataResponse);
// Then you can ask AutoMapper to project the IQueryable directly to your DTO
List<Classes.DataResponse> res = con.DataRepoes
.Where(rx => iaccess.Contains(rx.STOREID))
.ProjectTo<Classes.DataResponse>()
.ToList();
Upvotes: 2
Reputation: 572
This is not possible using LINQ. However you can use "AutoMapper" to acheive this. Just CreateMap for these two class and then Map them
Mapper.CreateMap<DataResponse,DataRepo>();//Assuming DataRepoes is collection of DataRepo types
List<Classes.DataResponse> res = (from rx in con.DataRepoes
where iaccess.Contains(rx.STOREID)
select Mapper.Map<Classes.DataResponse>(rx)).
ToList<Classes.DataResponse>();
Hope that helps!!
Upvotes: 1