简体   繁体   中英

How to reuse data mapping Expression as a compiled Expression?

I have this code in LinqPad:

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

That successfully queries SQL for two table fields instead of all of them using this POCO class (not sure if the inner static makes the outer class static too):

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;}
}

So I'd like to write the first line of code this way:

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

I've tried writing this code:

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

Which produces the same result, but it retrieves the entire Product record in SQL instead of just the two fields we need. I've also tried this code, but it requires doing var a = Product.AsDDL().Take(1).Dump(); . I need it in the other form (o => o.AsDDL()) . (I've even tried using a constructor function, but SQL doesn't understand the function in that form.)

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

How would one code the Linq Expression?

AutoMapper might be for you. see this: https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions

It requires to configure mapping once, but after that, you can reuse DTO mapping anytime.

Here's an example from it:

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

This is what worked for me. I define the Expression as above, then a compile on the Expression right below it. This is really a View Model taking a POCO and mapping it to itself. You can add attributes to the methods so that JSON.NET doesn't serialize them (assuming...) The reason for Map and ToMap is the first is used to project fields in Entity Framework for example, and the other is used on in-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;}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM