使用DefaultIfEmpty改进Linq子查询

时间:2011-08-04 11:01:54

标签: linq entity-framework performance

我有以下数据库结构(简化)

存储

StoreId
RateId

产品

ProductId
Name

价格

RateId
Name
IsDefault

价格

PriceId
ProductID
RateId
UnitPrice

我有产品,每个产品都可以有倍数价格,具体取决于费率表。我有多个商店,每个商店都有一个默认费率(rateId)。如果在给定费率(rateId)的价格表中未找到产品价格,则返回默认rateId和Product的价格。

现在是UI代码:

    public ActionResult All() {

        // Retrieve all products from database
        var products = db.GetAllStoreProducts(StoreSettings.Default.StoreId)
            .OrderBy(p => p.DateCreated);

        var viewModel = new StoreBrowseViewModel() {
            Name = "Todos los Productos",
            Description = "Todos los Productos que forman parte de nuestro catálogo",
            StoreProducts = products.ToList()
        };

        return View("Browse1", viewModel);
    }

Linq代码:

    public IQueryable<Product> GetProducts() {

        return storeDB.Products
            .Include("Price");
    }

    public IQueryable<StoreProduct> GetAllStoreProducts(Guid storeId) {

        var store = storeDB.Stores
            .SingleOrDefault(s => s.StoreId == storeId);

        var products = GetProducts()
                .Where(p => p.Visible)
                .OrderBy(p => p.Name)
                .Select(p => new StoreProduct() {
                    Family = p.Family,
                    Category = p.Category,
                    MetricType = p.MetricType,
                    Name = p.Name,
                    PublicArtUrl = p.ProductArtUrl,
                    DateCreated = p.DateCreated,
                    DateUpdated = p.DateModified,
                    UnitPrice = p.Prices
                        .Where(pc => pc.Rate.RateId == store.RateId)
                        .Select(b => b.UnitPrice)
                        .DefaultIfEmpty(p.Prices.FirstOrDefault(p2 => p2.Rate.IsDefault).UnitPrice)
                        .FirstOrDefault()
                });

        return products;
    }

代码工作正常,我得到了给定商店的正确价格或默认价格,如果没有找到'覆盖'但是......有什么想法来提高linq查询的性能? (不想使用sproc)

1 个答案:

答案 0 :(得分:1)

  • 您正在执行2个查询,这些查询可以合并为一个。
  • 您只为RateId属性选择整个商店实体。

此外: 我们使用以下规则来创建非常高性能的linq查询:

  • Use compiled queries 它大大加快了查询性能。它提供了查询的编译和缓存以供重用。查询编译一次后,您的程序可以使用其他参数执行它。
  • 选择PresentationModels而不是实体。实体比代表实体的简单类重得多。
  • 切勿使用“包含”。这是一个真正的性能猪。只需创建一个查询即可立即获取所有信息。