2015-12-07 6 views
6

Ich führe eine ASP.NET WebAPI2-Anwendung mit Entity-Framework 6 und MSSQL-Server-Datenbank. Der IoC-Container ist Castle Windsor. Ich habe eine Methode in meinem Repository, die ich verwende, um einige Details für einen Benutzer aus der DB zu erhalten. Da ich nicht jede Spalte brauche, dachte ich, ich würde Projektion verwenden. Das Problem besteht darin, dass das generierte SQL ALLE Spalten in meiner Tabelle auswählt. Hier ist der DbContextEntity Framework 6 Projektion generiert SQL entspricht "Select *" und erzeugt keine WHERE-Klausel

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

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

Hier ist, wo der Kontext, in dem Repository deklariert/initialisiert

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 
} 

und hier ist das Verfahren im 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     
    }; 
} 

Hier ist die Ausgabe von 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] 

Ich denke, ich mache etwas falsch, aber ich kann nicht herausfinden, was. Irgendwelche Ideen werden geschätzt.

EDIT: Ich habe gerade etwas seltsam bemerkt - in der generierten SQL gibt es keine WHERE-Klausel, was bedeutet, dass alle Zeilen aus der Datenbank ausgewählt, zum Client gebracht und dort gefiltert werden. EDIT 2: das gleiche SQL wird mithilfe der LINQ-Abfragesyntax erstellt. EDIT 3: Nach dem Schreiben eines Komponententests, bei dem ich das Repository und den Dienst manuell instanziiere (anstatt es CastleWindsor zu überlassen), hat das beim Ausführen des Tests erzeugte SQL die WHERE-Klausel.

+0

In Ihrem Kontext, wie sind die Sätze deklariert? Haben sie 'public virtual' oder nur' public'? – GregoryHouseMD

+0

Warum 'context.Set ()' und nicht 'context.secUsers()'? – GregoryHouseMD

+0

@GregoryHouseMD, weil der Kontext im Repository als DbContext übergeben wird. Ich habe versucht, es auf SecurityContext zu übertragen, bevor ich auf Ihren Kommentar antwortete, aber es ergab keinen Unterschied. – user2936023

Antwort

2

Wenn Ihre context ist etwas, das ein IEnumerable<T> (und nicht IQueryable<T>) von der Set<T> Methode gibt, dann ist das dein Problem, weil der Ausdruck:

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

... wird die gesamte Tabelle in dem Speicher gelesen, und dann wenden Sie die Where Klausel und die Projektion (Select). Also, Sie würde erwarten SELECT * FROM table Verhalten.

Die DbContext Klassenimplementierung von Set<T> gibt eine DbSet<T> zurück, die IQueryable<T> implementiert, also wäre das OK. Aber da es scheint, dass Sie eine benutzerdefinierte Repository-Implementierung haben, bin ich misstrauisch, was sonst hinter den Kulissen passieren könnte ...

Verwandte Themen