0

我正在使用这个表达式来获取所有产品:

Expression<Func<Product, ProductInCityDto>> GetAllProducts
{
    get
    {
        return product => new ProductInCityDto
        {
             ProductName = product.ProductName,
             CityName = product.Store.City.Name,
             CountryName = product.Store.City.Country.Name,
             ProductAvgPrice =  CalculateAvg(product)
             . 
             . 
             .  
        }
    }
}

我正在使用函数 CalculateAvg 来计算产品的平均价格。计算是在单独的函数中,因为我在几个地方使用了这个代码。但是,这种方法会导致对数据库的多次调用。是否可以用 Linq 表达式替换函数 CalculateAvg,以便只调用一次数据库?

编辑:

函数 CalculateAvg 看起来像这样:

public static decimal CalculateAvg(object tempObj)
{
   Product obj = tempObj as Product; 
   return Convert.ToDecimal
          (obj.Sales.Where(n => n.type != 1)
                 .Average(n=>n.Price)
          );
}
4

2 回答 2

0

首先,我会将您的函数重构为扩展方法并删除转换以隔离一些可能性。请记住,您必须在静态类中放置扩展方法。

public static double CalculateAvg(this Product product)
{
   return product.Sales.Where(n => n.type != 1).Average(n=>n.Price);
}

如果这仍然会导致多次往返,请发布您在分析器中看到的查询,以便我们可以处理。

于 2013-02-22T13:54:21.423 回答
0

困难的部分不是转换为 Linq 表达式。困难的部分是表达式的调用。这很难。但最糟糕的是,它不是类型安全的,并且涉及类似于反射的东西。

真正的魔法部分是 IQueryable.Provider.Execute(Expression)..

你当然可以试试这个......但它绝不是经过测试的。更不用说,非常丑陋。

Expression<Func<Product, ProductInCityDto>> GetAllProducts
{
    get
    {
        return product => new ProductInCityDto
        {
             ProductName = product.ProductName,
             CityName = product.Store.City.Name,
             CountryName = product.Store.City.Country.Name,
             //Bit of a hack to coerce the Provider out...
             ProductAvgPrice = product.Sales
                    .AsQueryable.Provider
                    .Execute<double>(CalculateAvg(product), Expression.Constant(product, typeof (Product)) ),
             . 
             . 
             .  
        }
    }
}

public Expression<Func<Product, double>> CalculateAvg()
{
    return product => product.Sales.Where(n => n.type != 1).Average(n=>n.Price);
}
于 2013-02-25T14:14:34.937 回答