实体框架

时间:2016-12-04 07:29:50

标签: c# entity-framework 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

3 个答案:

答案 0 :(得分: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 Butler great answer的帮助下)

答案 1 :(得分:0)

如果您不想每次都写地图,可以使用优秀的图书馆http://automapper.org/ 使用此库,您可以定义地图并自动映射所有属性

答案 2 :(得分: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包。