Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用DefaultIfEmpty改进Linq子查询_Linq_Entity Framework_Performance - Fatal编程技术网

使用DefaultIfEmpty改进Linq子查询

使用DefaultIfEmpty改进Linq子查询,linq,entity-framework,performance,Linq,Entity Framework,Performance,我有以下数据库结构(简化) 贮藏 产品 ProductId Name 费率 价格 我有产品,根据费率表,每种产品都可以有倍数的价格。我有多个商店,每个商店都有一个默认利率(rateId)。如果在给定费率(rateId)的价格表中找不到产品的价格,则返回默认rateId和产品的价格 现在,用户界面代码: public ActionResult All() { // Retrieve all products from database var produ

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

贮藏

产品

ProductId
Name
费率

价格

我有产品,根据费率表,每种产品都可以有倍数的价格。我有多个商店,每个商店都有一个默认利率(rateId)。如果在给定费率(rateId)的价格表中找不到产品的价格,则返回默认rateId和产品的价格

现在,用户界面代码:

    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;
    }
public IQueryable GetProducts(){
返回storeDB.Products
.包括(“价格”);
}
公共IQueryable GetAllStoreProducts(Guid storeId){
var store=storeDB.Stores
.SingleOrDefault(s=>s.StoreId==StoreId);
var products=GetProducts()
.其中(p=>p.Visible)
.OrderBy(p=>p.Name)
.选择(p=>new StoreProduct(){
家庭,
类别=p.类别,
MetricType=p.MetricType,
名称=p.名称,
PublicArtUrl=p.ProductArtUrl,
DateCreated=p.DateCreated,
DateUpdated=p.DateModified,
单价=单价
.Where(pc=>pc.Rate.RateId==store.RateId)
.选择(b=>b.单价)
.DefaultIfEmpty(p.Prices.FirstOrDefault(p2=>p2.Rate.IsDefault).UnitPrice)
.FirstOrDefault()
});
退货产品;
}
代码运行正常,我得到给定商店的正确价格,或者如果没有找到“覆盖”,则得到默认价格,但是。。。有没有改进linq查询性能的想法?(不想使用存储过程)

  • 您正在执行两个查询,它们可以组合成一个查询
  • 仅为RateId属性选择整个商店实体
此外: 我们使用以下规则创建非常高性能的linq查询:

  • 它极大地提高了查询性能。它提供查询的编译和缓存以供重用。在查询编译一次之后,您的程序可以使用其他参数执行它
  • 选择而不是实体。实体比表示实体的简单类重得多
  • 永远不要使用“包含”。这是一个真正的性能猪。只需创建一个一次获取所有信息的查询

如果您觉得性能很差,请运行SQL profiler并检查为上述linq查询生成的SQL查询。实际上,这并不差,但linq表达式可能会得到改进或变得更优雅
PriceId
ProductID
RateId
UnitPrice
    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);
    }
    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;
    }