2013-02-22 47 views
3

我有这样的表达,生成一个查询到数据库:LINQ到SQL:优化兰巴表达 - 干净的代码

db = new MyDataContext(); 
var productInCity = db.Products 
         .Where(n => n.id == 2) 
         .Select(k => new ProductInCityDto() 
         { 
           ProductName = k.ProductName, 
           CityName = k.Store.City.Name, 
           CountryName = k.Store.City.Country.Name 
           . 
           . 
           . 
         }) 
         .FirstOrDefault(); 

我想使代码更清洁,通过将映射功能,扩展方法或对象的构造函数,像这样:

db = new MyDataContext(); 
var productInCity = db.Products 
         .Where(n => n.id == 2) 
         .Select(k => new ProductInCityDto(k)) 
         .FirstOrDefault(); 

但是,在这种情况下,会产生多个查询数据库(我使用LinqToSql探查)。

有没有办法隔离映射(Select语句)以获得更好的代码可读性?

+1

您的DataContext是否使用LazyLoading? – Carsten 2013-02-22 09:26:56

回答

3

是的,如果您查看IQueryable上Select扩展方法的实际签名,您会发现它不会使用函数,而是使用Expression>。

所以,只要做到这一点...

Expression<Func<Product, ProductInCityDto>> MyMappingExpression 
{ 
    get 
    { 
     return product => new ProductInCityDto 
     { 
      ... 
     } 
    } 
} 

然后

db = new MyDataContext(); 
      var productInCity = db.Products.Where(n => n.id == 2) 
       .Select(MyMappingExpression) 
      .FirstOrDefault(); 

如果您需要使用MyMappingExpression的过程中,你可能会希望将其转换为一个

Func<Product, ProductInCityDto> 

通过调用Expression.Compile()方法。

+0

谢谢。有用。 – Programmer 2013-02-22 09:39:52

+0

我只改 '表达> MyMappingExpression' 到 '表达> MyMappingExpression' – Programmer 2013-02-22 09:51:11

+0

@AleksandarMafilovski很抱歉的错误。固定。 – Aron 2013-02-24 19:21:23

0

除了手动创建映射,您可以使用AutoMapper。但是,如果您不想使用第三方工具创建映射,只需将查询更改为以下内容;

var productInCity = new ProductInCity(
        db.Products.Include("Store").SingleOrDefault(n => n.id == 2));