实体框架6的投影生成等效于“0”的SQL;选择“*”;并且不产生WHERE子句

本文关键字:选择 子句 WHERE 投影 框架 实体 SQL | 更新日期: 2023-09-27 18:26:02

我正在维护一个带有Entity framework 6和MSSQL服务器数据库的ASP.NET WebAPI2应用程序。IoC集装箱是温莎城堡。我在我的存储库中有一个方法,用于从DB中获取用户的一些详细信息。由于我不需要每一列,所以我想我应该使用投影。问题是生成的SQL选择了我表中的所有列。这是DbContext

public partial class SecurityContext : DbContext
{
    public SecurityContext()
        : base("name=SecurityContext")
    {
    }
    public virtual DbSet<User> secUsers { get; set; }
}

以下是在存储库中声明/初始化上下文的位置

public class BaseRepository<T> : IRepository<T> where T : class
{
    protected DbContext context;
    public BaseRepository()
    {
        context = new SecurityContext();
    }
    public BaseRepository(DbContext context)
    {
        this.context = context;
    } 
    //elided
}

这是储存库中的方法

public User FindUserForLoginVerification(string name)
{         
    var loginInfo = context.Set<User>()
        .Where(c => c.LoginName == name)
        .Select(c => new 
        { 
            LoginName = c.LoginName, 
            Password = c.HashedPassword, 
            Salt = c.PasswordHashSalt 
        })
        .SingleOrDefault();
    return new User() { 
        LoginName = loginInfo.LoginName, 
        HashedPassword = loginInfo.Password, 
        PasswordHashSalt = loginInfo.Salt                
    };
}

这是输出SQL。

SELECT 
[Extent1].[UserId] AS [UserId], 
[Extent1].[CreatedByUserId] AS [CreatedByUserId], 
[Extent1].[Comment] AS [Comment], 
[Extent1].[CreatedDate] AS [CreatedDate], 
[Extent1].[DefaultCulture] AS [DefaultCulture], 
[Extent1].[EmailAddress] AS [EmailAddress], 
[Extent1].[FirstName] AS [FirstName], 
[Extent1].[IsDeleted] AS [IsDeleted], 
[Extent1].[IsExcludedFromPasswordPolicy] AS [IsExcludedFromPasswordPolicy], 
[Extent1].[IsChangePassword] AS [IsChangePassword], 
[Extent1].[IsLocked] AS [IsLocked], 
[Extent1].[LastName] AS [LastName], 
[Extent1].[LastPasswordChangeDate] AS [LastPasswordChangeDate], 
[Extent1].[LoginName] AS [LoginName], 
[Extent1].[NumberOfFailedLoginAttempts] AS [NumberOfFailedLoginAttempts], 
[Extent1].[PasswordHash] AS [PasswordHash], 
[Extent1].[PasswordHashSalt] AS [PasswordHashSalt]
[Extent1].[UpdatedDate] AS [UpdatedDate]
FROM [dbo].[User] AS [Extent1]

我想我做错了什么,但我不知道是什么。任何想法都将不胜感激。

EDIT:我刚刚注意到一些奇怪的事情——在生成的SQL中没有WHERE子句,这意味着所有的行都是从数据库中选择的,带到客户端,并在那里进行过滤。EDIT 2:使用LINQ查询语法生成相同的SQL。编辑3:在编写了一个单元测试之后,我手动实例化了存储库和服务(而不是将其留给CastleWindsor),运行测试时生成的SQL具有where子句。

实体框架6的投影生成等效于“0”的SQL;选择“*”;并且不产生WHERE子句

如果您的context是从Set<T>方法返回IEnumerable<T>(而不是IQueryable<T>)的东西,那么这就是您的问题,因为表达式:

context.Set<User>
.Where(...)
.Select(...)
.SingleOrDefault()

将整个表读取到内存中,然后应用Where子句和投影(Select)。因此,您期望SELECT * FROM table的行为。

Set<T>DbContext类实现返回了一个DbSet<T>,它确实实现了IQueryable<T>,所以这是可以的。但由于看起来你有一个自定义的存储库实现,我怀疑幕后还会发生什么。。。