2016-02-18 2 views
6

Problem: Ich mag die genaue sql unten in der gewünschten Ausgabe mit linq Syntax (Entity Framework 7)LEFT JOIN, nachdem eine in der Gruppe in Linq Entity-Framework (Kern)

Das Ziel der erzeugen Frage ist, den genauen sql unten zu erzeugen! gewünschte Ausgabe

select a.AppUserId, u.Email, a.FirstName, a.MiddleName, a.LastName, a.IsInternal, a.AspNetUserId, a.PictureLink, a.SignatureLink, a.PhoneNumber, a.Extension, a.FaxNumber, a.MobileNumber, a.Skype, r.Name as 'Role', a.SupervisorId, a.BackUpId, a.HasAutoAssignClaims, a.IsActive 
from AppUser a 
join AspNetUsers u on a.AspNetUserId = u.Id 
left join AspNetUserRoles ur on u.Id = ur.UserId 
left join AspNetRoles r on ur.RoleId = r.Id 

Ich habe nur genau die gleiche SQL zu bekommen in der Lage, aber mit innerer Joins. Ich kann nicht scheinen, die zwei linken Verbindungen zu bekommen. Der Code hier unten, wie ich die inneren Joins generieren konnte und auch einen fehlgeschlagenen Versuch, die linken Joins zu generieren.

SELECT [a].[AppUserId], [a].[FirstName], [a].[MiddleName], [a].[LastName], [a].[IsInternal], [a].[AspNetUserId], [a].[PictureLink], [a].[SignatureLink], [a].[PhoneNumber], [a].[Extension], [a].[FaxNumber], [a].[MobileNumber], [a].[Skype], [a].[SupervisorId], [a].[BackUpId], [a].[HasAutoAssignClaims], [a].[IsActive] 
FROM [AppUser] AS [a] 
INNER JOIN [AspNetUsers] AS [b] ON [a].[AspNetUserId] = [b].[Id] 
INNER JOIN [AspNetUserRoles] AS [c] ON [b].[Id] = [c].[UserId] 
INNER JOIN [AspNetRoles] AS [d] ON [a].[RoleId] = [d].[Id] 

Code mit INNER JOIN funktioniert, aber ich will links verbindet ....:

var query = (
           //INNER JOIN 
           from a in _dbCtx.AppUser 
           join b in _dbCtx.Users 
           on a.AspNetUserId equals b.Id 


           ////LEFT JOIN 
           join c in _dbCtx.UserRoles 
           on b.Id equals c.UserId 

           // // //LEFT JOIN (if you wanted right join the easiest way is to flip the order of the tables. 
           join d in _dbCtx.Roles 
           on a.RoleId equals d.Id 





          select new 
          { 
           AppUserId = a.AppUserId, 
           //Email = b.Email, 
           FirstName = a.FirstName, 
           MiddleName = a.MiddleName, 
           LastName = a.LastName, 
           IsInternal = a.IsInternal, 
           AspNetUserId = a.AspNetUserId, 
           PictureLink = a.PictureLink, 
           SignatureLink = a.SignatureLink, 
           PhoneNumber = a.PhoneNumber, 
           Extension = a.Extension, 
           FaxNumber = a.FaxNumber, 
           MobileNumber = a.MobileNumber, 
           Skype = a.Skype, 
           //Role = d.Name != null ? string.Empty :d.Name , 
           SupervisorId = a.SupervisorId, 
           BackUpId = a.BackUpId, 
           HasAutoAssignClaims = a.HasAutoAssignClaims, 
           IsActive = a.IsActive 

          }).ToList(); 

Code mit links ... Join die ich einige Konzept funktioniert nicht

was tut fehlt Arbeit ist, dass auf g2.RoleId gleich d.Id in Gruppe3 Linie der g2 ist nicht verfügbar. Also wie würde ich c.RoleId für meine nächste Linksmitgliedschaft verfügbar machen? Grundsätzlich, nachdem Sie etwas gruppiert haben, können Sie es anscheinend nicht mehr verwenden.

 var LeftJoin= (
          //INNER JOIN 
          from a in _dbCtx.AppUser 
          join b in _dbCtx.Users 
          on a.AspNetUserId equals b.Id 


          ////LEFT JOIN 
          join c in _dbCtx.UserRoles 
          on b.Id equals c.UserId into group2 
          from g2 in group2.DefaultIfEmpty() //makes it left join 



          join d in _dbCtx.Roles 
          on g2.RoleId equals d.Id into group3 
          from g3 in group3.DefaultIfEmpty() 

          select new 
          { 
           AppUserId = a.AppUserId, 
           Email = b.Email, 
           FirstName = a.FirstName, 
           MiddleName = a.MiddleName, 
           LastName = a.LastName, 
           IsInternal = a.IsInternal, 
           AspNetUserId = a.AspNetUserId, 
           PictureLink = a.PictureLink, 
           SignatureLink = a.SignatureLink, 
           PhoneNumber = a.PhoneNumber, 
           Extension = a.Extension, 
           FaxNumber = a.FaxNumber, 
           MobileNumber = a.MobileNumber, 
           Skype = a.Skype, 
           Role = g3.Name != null ? string.Empty :g3.Name , 
           SupervisorId = a.SupervisorId, 
           BackUpId = a.BackUpId, 
           HasAutoAssignClaims = a.HasAutoAssignClaims, 
           IsActive = a.IsActive 

          }).ToList(); 

enter image description here

+0

Sie sollten dies weiter ausführen: 'einige Konzept funktioniert nicht ' –

+0

Ich habe ausgearbeitet, dass g2.RoleId ist nicht mehr verfügbar, wenn ich auf g2.RoleId gleich d.Id in group3. Das Gesamtziel besteht darin, die obige Abfrage mit den linken Joins in welcher Methodik auch immer zu replizieren. – hidden

+0

Was meinst du mit * nicht verfügbar *? Syntaktisch sieht das wie eine korrekte Aussage aus. –

Antwort

0

Dies ist eine Arbeit um, dass die Daten mit einer sehr schlechten Abfrage generiert. Es generiert eine Reihe von Aufrufen an die Datenbank, die dieselbe Ergebnismenge ergeben. Es ist jedoch definitiv nicht die beste Abfrage für den Job. Ich warte immer noch auf RC2 und ich werde die Antwort aktualisieren.

3

Wenn ich Sie richtig verstanden habe, ist das Problem, dass EF nicht LEft Join erzeugt. Wenn ja, dann Lösung ist ziemlich einfach Ihre Entitäten sollten zum Beispiel Nullable-Eigenschaft haben

public class SomeClass 
    { 
     public int Id { get; set; } 
     public int? CategoryId { get; set; } 
     public Category Category {get;set:} 
    } 

Eine Möglichkeit, die in meinem Kopf ist

_dbCtx.SqlQuery<T>(SqlStringHEre).ToList() 

Andere Option und aspnet Tabellen würde ich es anders machen

var query = _dbCtx.AppUser 
.Include(apu=>apu.AspNetUser) 
.Include(apu=>apu.AspNetUser.Roles) 
.Include(apu=>apu.AspNetUser.Roles.Select(r=>r.Role)) 
.ToList(); 

aber hier ist ein Problem, wie wir in Kommentaren sprechen, dass IdentityUserRole Reference zu Rolle nicht so beheben wir das haben. Klasse erstellen

public class UserToRole : IdentityUserRole<int> 
    { 
     public Role Role { get; set; } 
    } 

erweitern Sie dann Ihren Benutzerklasse

public class YourUser : IdentityUser<int, IdentityUserLogin<int>, UserToRole, IdentityUserClaim<int>> 

Jetzt können Sie tun, was Sie

auf diese Frage kommt jemand
_db.Users.Select(u=>u.Roles.Select(r=>r.Role.Name)) 
+0

Leider erzeugt das sql nicht äquivalent zu meiner Abfrage oben. Dies beinhaltet auch nicht den Rollennamen, der in der Abfrage sehr wichtig ist. Es ist auch nicht die beste Sql. Denken Sie daran, was ich will, ist die genaue sql generieren ich oben in der Frage gestellt. Option [a]. [Benutzer-ID], [a]. [RoleId] FROM [AspNetUserRoles] AS [a] INNER JOIN ( SELECT DISTINCT * FROM [AnwBenutzer] AS [APU] INNER JOIN [AspNetUsers] AS [ a] Ein [apu]. [AspNetUserId] = [a]. [Id] INNERER VERBINDUNG [AspNetUsers] AS [a0] EIN [apu]. [AspNetUserId] = [a0]. [Id] ORDER BY [a] . [Id] – hidden

+0

@hidden können Sie erklären, warum Sie genau die gleiche Frage benötigen? –

+0

weil ich kann nicht glauben, dass es nicht möglich ist, eine einfache linke Join zu erzeugen ... Ich habe die innere Join-Äquivalent, warum es so schwer ist, ein einfaches zu tun link join – hidden

4

Falls Sie möchten, denken, es hat nicht beantwortet wurde, ist die Antwort derzeit in einer Kommentarkette nach der Frage begraben. Ich paraphrasiere nur die Schlüsselkommentare hier.

Das Problem ist, dass Entity Framework 7 derzeit eine release candidate ist und einige Fehler hat. Einer dieser Fehler (Left Join doesn't work if the filter is composed on top) verursacht den Fehler des linken Joins, der vom OP festgestellt wurde.

Die Lösung ist jetzt, zu Entity Framework 6 zurückzukehren oder vorübergehend eine gespeicherte Prozedur oder Inline-SQL zu verwenden, bis der Fehler behoben ist.