2016-12-04 72 views
3

在我的應用程序的多個報告,因此需要對一些表,許多領域都在大多數報告常見的,作爲一個樣本:可重複使用LINQ選擇查詢

public class ReportStudent 
{ 
    public int Id {get; set;} 
    public string Name {get; set;} 
    public string Family {get; set;} 
    public DateTime BirthDate {get; set;} 
    public DateTime RegisterDate {get; set;} 
    public Double Average {get; set;} 
    public string FatherName {get; set;} 
    public string MotherName {get; set;} 
} 

var list1 = context.Students.Select(e=> new ReportStudent 
{ 
    Id = e.Id 
    Name = e.Name 
    Family = e.Family 
    BirthDate = e.BirthDate 
    RegisterDate = e.RegisterDate 
    FatherName = e.FatherName 
    MotherName = e.MotherName 
}).ToList(); 

var list2 = context.Students.Select(e=> new ReportStudent 
{ 
    Id = e.Id 
    Name = e.Name 
    Family = e.Family 
    BirthDate = e.BirthDate 
    RegisterDate = e.RegisterDate 
    Average = e.Average 
}).ToList(); 

我怎麼能寫這個地圖只有一次?這些字段在list1和list2中很常見。

Id = e.Id 
Name = e.Name 
Family = e.Family 
BirthDate = e.BirthDate 
RegisterDate = e.RegisterDate 
+0

一個字:AutoMapper。 –

回答

4

首先,定義將包含公共投影的表達需要:

Expression<Func<ReportStudent, ReportStudent>> commonProjection = e => new ReportStudent 
{ 
    Id = e.Id, 
    Name = e.Name, 
    Family = e.Family, 
    BirthDate = e.BirthDate, 
    RegisterDate = e.RegisterDate, 
}; 

然後具有將修改這個表達式,以反映附加綁定的方法:

public static Expression<Func<ReportStudent, ReportStudent>> MergeBindings(Expression<Func<ReportStudent, ReportStudent>> expr, Expression<Func<ReportStudent, ReportStudent>> newExpr) 
{ 
    var reportStudentType = typeof(ReportStudent); 
    var eParameter = expr.Parameters.First(); 
    var eNew = Expression.New(reportStudentType); 

    var memberInitExpr = expr.Body as MemberInitExpression; 
    var memberInitNewExpr = newExpr.Body as MemberInitExpression; 
    var allBindings = memberInitExpr.Bindings.Concat(memberInitNewExpr.Bindings.Select(x => 
     Expression.Bind(x.Member, Expression.Property(eParameter, x.Member as PropertyInfo) 
    ))); 

    var eInit = Expression.MemberInit(eNew, allBindings); 
    var lambda = Expression.Lambda<Func<ReportStudent, ReportStudent>>(eInit, eParameter); 

    return lambda; 
} 

用法:

var withParentsExpr = MergeBindings(commonProjection, e => new ReportStudent 
{ 
    FatherName = e.FatherName, 
    MotherName = e.MotherName 
}); 

var list1 = context.Students.Select(withParentsExpr).ToList(); 

var withAverageExpr = MergeBindings(commonProjection, e => new ReportStudent 
{ 
    Average = e.Average 
}); 

var list2 = context.Students.Select(withAverageExpr).ToList(); 

(從@Nicholas巴特勒great answer一些幫助)

+0

tnx for answer,但存在錯誤「方法的類型參數」Queryable.Select (IQueryable ,Expression >)'不能從該用法推斷。嘗試指定類型參數明確地「 –

+0

@MohammadAkbari,錯誤發生在哪裏? – haim770

+0

on select,context.Students.Select(withParentsExpr).ToList() –

0

如果你不想每次寫的地圖,你可以用偉大的圖書館http://automapper.org/ 有了這個庫,你可以定義地圖,它會自動映射所有屬性

0

您可以創建,讓一個函數說你有​​

public StudentReport ParseStudentReport(Student e) 
{ 
    return new StutentReport{ 
     Id = e.Id 
     Name = e.Name 
     Family = e.Family 
     BirthDate = e.BirthDate 
     RegisterDate = e.RegisterDate 
    } 
} 

那麼你的SELECT語句中使用它

var list2 = context.Students.Select(ParseStudentReport); 

然後添加其餘的屬性,或者您可以使用AutoMapper,它可以在github上找到或作爲nuget包。

+0

如何添加剩餘的屬性,PLZ給出一個例子 –

+0

這不會返回Entity Framework可以轉換成存儲查詢的'Expression' – haim770