在我的应用程序中,某些表需要多个报告,许多字段在大多数报告中都很常见,作为示例:

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();

我怎么能只写一次这张 map ?这些字段在 list1 和 list2 中很常见。
Id = e.Id
Name = e.Name
Family = e.Family
BirthDate = e.BirthDate
RegisterDate = e.RegisterDate

最佳答案

首先,定义一个将包含您的常见投影需求的表达式:

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

然后有一个方法来修改这个表达式以反射(reflect)额外的绑定(bind):
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 Butler great answer 的帮助下)

关于c# - Entity Framework 中可重用的 linq 选择查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40956445/

10-11 01:07