【问题标题】:LINQ-to-Entities WHERE condition not executed on sql serverLINQ-to-Entities WHERE 条件未在 sql server 上执行
【发布时间】:2021-01-14 09:21:49
【问题描述】:

我已经按照Adam Freeman 的书学习了 ASP.NET MVC 5。我已经实现了书中描述的存储库模式。我正在使用 WHERE 并使用 SQL-EventProfiler 记录 SQL 命令,然后我将看不到 WHERE 条件。

这是我的示例代码,用于我使用 Ninject 的存储库:

 public interface IHelpRepository {

        IEnumerable<Help> Helps { get; }

    }
    public class HelpRepository : IHelpRepository {
        private HelpDBContext context = new HelpDBContext();

        public IEnumerable<Help> Helps {
            get { return context.Helps; }
        }
    }
    public class Help {

        [Required]
        [Key]
        public int Id { get; set; }

        [Required]
        public string Title { get; set; }

        [Required]
        public string Description { get; set; }
    }

    public class HelpController : Controller {

        private IHelpRepository HelpRepository;

        public HelpController (IHelpRepository helpRepository) {
            this.HelpRepository= helpRepository;
        }

        public ActionResult HelpDescription(int Id) {

            Help help = helpRepository.Helps.Where(h => h.Id == Id).SingleOrDefault<Help>();

            return View("HelpDescription", help);
        }
    }

生成的 SQL 命令 (XEventProfiler):

SELECT [Extent1].[Id] AS [Id], [Extent1].[Title] AS [Title], [Extent1].[Description] AS [Description] FROM [dbo].[Helps] AS [Extent1 ]

为什么生成的 SQL 命令中不包含 WHERE?

【问题讨论】:

  • 在 EF 等更高级别的 ORM 之上使用时,通用存储库实际上是一种模式。你的问题是后果之一。 DbContetx 不是连接或数据库模型,它是控制多个实体的工作单元。 DbSet已经是一个存储库。通过转换为IEnumerable,您实际上是在执行查询并将所有内容加载到内存中
  • 现在,您的存储库类只是委托给 DbSet 类,同时阻止您组合实体。这种贫乏的存储库类没有任何好处,只有问题。检查No need for repositories and unit of work with Entity Framework Core 看看有什么问题

标签: asp.net asp.net-mvc linq entity-framework-6 repository-pattern


【解决方案1】:

公共 IEnumerable 帮助 { 获取{返回上下文。帮助; } }

您在此处返回 IEnumerable,此时查询被执行。有两件事你可以摆脱它

  1. 第一个选项是返回 IQueryable 并使用 where 过滤器,然后像这样检查探查器
public IQueryable<Help> Helps {
            get { return context.Helps; }
        }

Help help = helpRepository.Helps.Where(h => h.Id == Id).SingleOrDefault<Help>();
  1. 第二种方法是创建一个repository方法,在方法中过滤并返回IEnumerable
public IEnumerable<Help> Where(Expression<Func<Help,bool>> where) 
{
     return context.Helps.Where(where);
}

要了解 IQueryable 和 IEnumerable 之间的区别,只需通过以下链接

IQueryable vs IEnumerable

IQueryable 始终在数据源上下文中执行查询,而 IEnumerable 在内存中工作,在从数据源提供程序获取数据后

【讨论】:

  • 添加简单地委托给底层 DbContext 的方法没有多大意义。这是问题代码的问题,而不是答案
  • 谢谢,这正在工作。我想知道为什么这本书没有涉及。他们展示了一个完全正常工作的应用程序,但他们从未指出他们的代码一次返回所有条目......如果我在我的应用程序中使用它,表格中有数百万行,那会很有趣,我会想知道关于糟糕的表现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 2013-10-23
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
相关资源
最近更新 更多