【问题标题】:Optimize LINQ to SQL statement that has foreign key access优化具有外键访问权限的 LINQ to SQL 语句
【发布时间】:2015-10-27 18:38:18
【问题描述】:

我有以下数据库图:

每个Product 使用LanguageKey 来确定其名称,每个LanguageKey 有多个LanguageValue 记录,其中包含每种语言的值。

现在在我的Controller 中,我想将我的Product 实体选择到ViewModel 对象中,所以我的语句如下所示:

 var model = new ProductListViewModel()
        {
            Products = products
                .Select(q => new ProductViewModel()
                {
                    ID = q.ID,
                    Name = q.LanguageKey.LanguageValues.FirstOrDefault(p => p.LanguageID == this.CurrentLanguage.ID && p.Active).Value,
                    Code = q.Code,

                    // Other code

简而言之,我已经有了所需的语言 ID,我需要获取确切的值。但是,当查看 VS 的诊断工具时,当执行查询树时(当我在视图中调用 foreach 语句时),我的应用程序执行了多个 SELECT 语句,每个语句对应一个 LanguageValue,如下所示:

"SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Active] AS [Active]
    FROM [dbo].[LanguageKey] AS [Extent1]
    WHERE [Extent1].[ID] = @EntityKeyValue1"

"SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[LanguageKeyID] AS [LanguageKeyID], 
    [Extent1].[LanguageID] AS [LanguageID], 
    [Extent1].[Value] AS [Value], 
    [Extent1].[Active] AS [Active]
    FROM [dbo].[LanguageValue] AS [Extent1]
    WHERE [Extent1].[LanguageKeyID] = @EntityKeyValue1"

是因为我使用的是FirstOrDefault()吗?有没有更好的方法来处理这个问题,因为我的应用程序在过滤后会经常处理大约 1k 条记录。

P.s:我也想知道为什么编译查询中没有Active谓词。

编辑:这就是我获得products 的方式(上下文是我的DbContext,函数在ProductService 类中,productService 是它的实例):

    public IEnumerable<Product> GetAllActiveProducts()
    {
        return this.Context.Products
            .Where(q => q.Active);
    }

    var products = productService.GetAllActiveProducts();

【问题讨论】:

  • 你是如何获取产品的?
  • @PraveenPaulose 对不起,我忘了。我添加了函数和调用。

标签: c# sql-server linq optimization


【解决方案1】:

您的GetAllActiveProducts() 应该返回IQueryable&lt;Product&gt;,而不是IEnumerable&lt;Product&gt;。通过返回IEnumerable&lt;Product&gt;,您实际上是在强制对该可枚举的任何进一步操作在客户端完成。这正是您所看到的行为。

【讨论】:

  • 天啊,没想到会这么简单!非常感谢,现在一切都在一个 SQL 调用中完成,查询时间从 16 秒缩短到了 800 毫秒!
  • 请再问一个问题,有时在我的Service 类中,我需要使用LINQ Select() 函数,它返回IEnumerable 而不是IQueryable。我应该如何处理?在Select() 之后调用AsQueryable() 有帮助吗?
  • @DatVM LINQ 提供了Enumerable.SelectQueryable.Select 扩展方法。前者接受任何IEnumerable 并返回IEnumerable。后者接受任何IQueryable 并返回IQueryable。如果您看到Select() 返回IEnumerable,那是因为您正在调用Enumerable.Select 重载,或者因为您的输入不可查询,或者因为您的投影是委托而不是表达式。 (检查声明:投影有不同的类型。)无论哪种方式,调用AsQueryable() 都很少是正确的解决方案。
  • 我明白了,非常感谢,确实来自ICollection&lt;&gt;。到时候我会继续努力的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多