如何重用数据映射表达式作为编译表达式?

时间:2015-04-03 15:57:25

标签: c# entity-framework-6

我在LinqPad中有这段代码:

void Main() { 
    var a = Product.Select( DDL.ToDDL).Take(1).Dump(); 
}

使用此POCO类成功查询SQL的两个表字段而不是所有表字段(不确定内部静态是否也使外部类也是静态的):

public class DDL {
    public static readonly Expression<Func<Product, DDL>> ToDDL =
        o => new DDL {
            id = o.identifier,
            name = o.pbfeattext
        };

    public int id {get;set;}
    public string name {get;set;}
}

所以我想以这种方式编写第一行代码:

var a = Product.Select(o => o.AsDDL()).Take(1).Dump();

我尝试过编写此代码:

public static class DDL3 {
    public static DDL AsDDL (this Product p) {
        return new DDL {
            id = p.identifier,
            name = p.pbfeattext
        };
    }
}

它会产生相同的结果,但它会在SQL中检索整个Product记录,而不仅仅是我们需要的两个字段。我也尝试过这段代码,但需要执行var a = Product.AsDDL().Take(1).Dump();。我需要另一种形式(o => o.AsDDL())。 (我甚至尝试过使用构造函数,但SQL并不了解该形式的函数。)

public static class DDL3
{
    public static DDL AsDDL (this Product p)
    {
        return new DDL {
            id = p.identifier,
            name = p.pbfeattext
        };
    }
}

如何编码Linq Expression?

2 个答案:

答案 0 :(得分:1)

AutoMapper可能适合您。看到这个:https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions

它需要配置一次映射,但之后,您可以随时重用DTO映射。

以下是一个例子:

public List<OrderLineDTO> GetLinesForOrder(int orderId)
{
  Mapper.CreateMap<OrderLine, OrderLineDTO>()
    .ForMember(dto => dto.Item, conf => conf.MapFrom(ol => ol.Item.Name);

  using (var context = new orderEntities())
  {
    return context.OrderLines.Where(ol => ol.OrderId == orderId)
             .Project().To<OrderLineDTO>().ToList();
  }
}

答案 1 :(得分:0)

这对我有用。我将Expression定义如上,然后在它下面的Expression上编译。这实际上是一个视图模型,它采用POCO并将其映射到自身。您可以向方法添加属性,以便JSON.NET不对它们进行序列化(假设...)Map和ToMap的原因是第一个用于在Entity Framework中项目字段,例如,另一个用于-ram collections。

public class DDL {
    public static readonly Expression<Func<Product, DDL>> Map =
        o => new DDL {
            id = o.identifier,
            name = o.pbfeattext
        };
    public static readonly Func<Product, DDL> ToMap = 
        DDL.Map.Compile();

    public int id {get;set;}
    public string name {get;set;}
}