2015-12-07 11 views
6

Sto mantenendo un'applicazione Web.API2 ASP.NET con Entity framework 6 e il database del server MSSQL. Il container IoC è Castle Windsor. Ho un metodo sul mio repository che uso per ottenere alcuni dettagli per un utente dal DB. Dal momento che non ho bisogno di ogni colonna, ho pensato di usare la proiezione. Il problema è che l'SQL generato seleziona TUTTE le colonne nella mia tabella. Ecco il DbContextEntity framework 6 projection genera SQL equivalente a "Select *" e non produce WHERE clausola

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

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

Ecco dove il contesto è dichiarata/inizializzato nel 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 
} 

ed ecco il metodo nel 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     
    }; 
} 

Ecco l'SQL uscita.

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] 

Immagino di fare qualcosa di sbagliato, ma non riesco a capire cosa. Qualsiasi idea sarà apprezzata.

EDIT: Ho appena notato qualcosa di strano - nell'SQL generato non c'è alcuna clausola WHERE, il che significa che tutte le righe vengono selezionate dal database, portate al client e filtrate lì. EDIT 2: lo stesso SQL viene prodotto utilizzando la sintassi della query LINQ. EDIT 3: Dopo aver scritto un test unitario in cui istanzio il repository e il servizio manualmente (invece di lasciarlo a CastleWindsor), l'SQL prodotto durante l'esecuzione del test ha la clausola WHERE.

+0

Nel tuo contesto, come vengono dichiarati i set? Hanno 'public virtual' o solo' public' – GregoryHouseMD

+0

Perché 'context.Set ()' e non 'context.secUsers()'? – GregoryHouseMD

+0

@GregoryHouseMD perché nel repository, il contesto viene passato come DbContext. Ho provato a trasmettere a SecurityContext prima di rispondere al tuo commento, ma non ha prodotto alcuna differenza. – user2936023

risposta

2

Se il context è qualcosa che restituisce un IEnumerable<T> (e non IQueryable<T>) dal metodo Set<T>, allora questo è il problema, perché l'espressione:

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

... leggerà l'intera tabella in memoria, e quindi applicare la clausola Where e la proiezione (Select). Quindi, è aspettarsi il comportamento SELECT * FROM table.

L'implementazione della classe DbContext di Set<T> restituisce un DbSet<T> che implementa IQueryable<T>, in modo che sia OK. Ma dal momento che sembra che tu abbia una implementazione di repository personalizzata, sono sospettoso su cos'altro potrebbe succedere dietro le quinte ...

Problemi correlati