简体   繁体   English

实体框架6投影生成等效于“ Select *”的SQL,并且不生成WHERE子句

[英]Entity framework 6 projection generates SQL equivalent to “Select *” and does not produce WHERE clause

I'm maintaining an ASP.NET WebAPI2 application with Entity framework 6 and MSSQL server database. 我正在使用实体框架6和MSSQL服务器数据库维护ASP.NET WebAPI2应用程序。 The IoC container is Castle Windsor. IoC容器是温莎城堡。 I have a method on my repository that I use to get some details for a user from DB. 我的存储库中有一个方法,用于从数据库获取用户的一些详细信息。 Since I don't need every column, I thought I'd use projection. 由于我不需要每一列,所以我认为我应该使用投影。 The problem is that the generated SQL selects ALL the columns in my table. 问题在于生成的SQL选择了我表中的所有列。 Here's the DbContext 这是DbContext

public partial class SecurityContext : DbContext
{
    public SecurityContext()
        : base("name=SecurityContext")
    {
    }

    public virtual DbSet<User> secUsers { get; set; }
}

Here's where the context is declared/initialized in the repository 这是在存储库中声明/初始化上下文的地方

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
}

and here's the method in the repository 这是存储库中的方法

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                
    };
}

Here's the output SQL. 这是输出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]

I guess I'm doing something wrong, but I can't figure out what. 我想我做错了,但我不知道该怎么办。 Any ideas will be appreciated. 任何想法将不胜感激。

EDIT: I just noticed something strange - in the generated SQL there's no WHERE clause, which means that all the rows are selected from the database, brought to the client, and filtered there. 编辑:我只是注意到一些奇怪的事情-在生成的SQL中没有WHERE子句,这意味着所有行都从数据库中选择,带到客户端并在那里进行过滤。 EDIT 2: the same SQL is produced by using the LINQ query syntax. 编辑2:使用LINQ查询语法产生相同的SQL。 EDIT 3: After writing a unit test where I instantiate the repository and service manually (instead of leaving it to CastleWindsor), the SQL produced when running the test has the WHERE clause. 编辑3:编写单元测试后,在其中手动实例化存储库和服务(而不是将其留给CastleWindsor),运行测试时生成的SQL具有WHERE子句。

If your context is something that returns an IEnumerable<T> (and not IQueryable<T> ) from the Set<T> method, then that's your problem, because the expression: 如果您的context是从Set<T>方法返回IEnumerable<T> (而不是IQueryable<T> )的东西,那么这就是您的问题,因为表达式:

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

...will read the whole table into memory, and then apply the Where clause and the projection ( Select ). ...将整个表读入内存, 然后应用Where子句和投影( Select )。 So, you would expect SELECT * FROM table behaviour. 因此,您期望SELECT * FROM table行为。

The DbContext class implementation of Set<T> returns a DbSet<T> which does implement IQueryable<T> , so that would be OK. Set<T>DbContext类实现返回一个DbSet<T> ,它确实实现了IQueryable<T> ,这样就可以了。 But since it looks like you have a custom repository implementation, I'm suspicious about what else might be going on behind the scenes... 但是由于您似乎已经有了一个自定义的存储库实现,因此我对幕后发生的事情感到怀疑...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM