2012-03-08 24 views
5

Lurker da molto tempo, poster prima volta. Ho trovato alcune buone risposte qui in passato, quindi la figura vorrei venire qui e vedere se posso avere un piccolo aiuto!Più join in query Entity Framework

Sono piuttosto nuovo a Linq e sto utilizzando Entity Framework per il mio oggetto. Ho un file .edmx nel mio progetto.

Prima di tutto ho importato la classe System.Linq.Dynamic utilizzando le pagine di esempio che è venuto con VS 2010, quindi posso aggiungere questo nella mia pagina:

utilizzando System.Linq.Dynamic;

Il problema è che non credo che il mio join funzioni correttamente.

Questo è il mio codice corrente:

private void FetchData() 
{ 
    using (var Context = new ProjectEntities()) 
    { 
     var Query = 
      Context.Users 
      .Join(Context.UserStats,   // Table to Join 
       u => u.msExchMailboxGuid,  // Column to Join From 
       us => us.MailboxGuid,   // Column to Join To 
       (u, us) => new     // Alias names from Tables 
       { 
        u, 
        us 
       }) 
      .Join(Context.TechContacts,   // Table to Join 
       u => u.u.UserPrincipalName,  // Column to Join From 
       tc => tc.UPN,     // Column to Join To 
       (u, tc) => new     // Alias names from Tables 
       { 
        u = u, 
        tc = tc 
       }) 
       .Where(u => true) 
       .OrderBy("u.u.CompanyName") 
       .Select("New(u.u.CompanyName,tc.UPN,u.us.TotalItemSize)"); 

     // Add Extra Filters 
     if (!(string.IsNullOrWhiteSpace(SearchCompanyNameTextBox.Text))) 
     { 

      Query = Query.Where("u.CompanyName.Contains(@0)", SearchCompanyNameTextBox.Text); 
     } 

     // Set the Record Count 
     GlobalVars.TotalRecords = Query.Count(); 

     // Add Paging 
     Query = Query 
      .Skip(GlobalVars.Skip) 
      .Take(GlobalVars.Take); 

     // GridView Datasource Binding 
     GridViewMailboxes.DataSource = Query; 
     GridViewMailboxes.DataBind(); 
    } 
} 

Come posso scriverlo in modo che funziona in questo modo sarebbe in SQL normale?

SELECT u.Column1, 
u.Column2, 
us.Column1, 
tc.Column1 
FROM Users AS u 
INNER JOIN UserStats AS us 
ON u.msExchMailboxGuid = us.MailboxGuid 
INNER JOIN TechContacts AS tc 
ON u.UserPrincipalName = tc.UPN 

ho bisogno di mantenere le clausole dinamiche .dove e nomi dei campi .SELECT, il problema come si può vedere in questo momento è che ho bisogno di fare uuCompanyName per tornare sul campo u.CompanyName come è nel mio si unisce due volte.

Ho cercato su Google per un po 'di tempo ma non ho ancora trovato i dadi.

Qualsiasi aiuto molto apprezzato!

MODIFICA - questa è la mia domanda corrente. Funziona ma è un po 'un incubo da vedere.

Orso con me. Volevo includere tutto qui se posso anche se è un po 'troppo.

La selezione dinamica delle colonne è un must per me. Altrimenti potrei anche restare con i miei adattatori da tavolo e i proc memorizzati. Essere in grado di ridurre la mia query a restituire meno dati è uno dei miei obiettivi con questo. Se qualcuno può suggerire miglioramenti, sono tutto orecchie?

Non riuscivo a trovare un modo per smettere di selezionare i miei join in elementi secondari, in SQL quando mi unisco devo semplicemente restituire le colonne che voglio tramite la mia istruzione SELECT.

private void FetchData() 
{ 
    using (var Context = new ProjectEntities()) 
    { 
     string Fields = GetDynamicFields(); 

     var Query = 
      Context.Users 
      .Join(Context.UserStats,   // Table to Join 
       u => u.msExchMailboxGuid,  // Column to Join From 
       us => us.MailboxGuid,   // Column to Join To 
       (u, us) => new     // Declare Columns for the next Join 
       { 
        ObjectGuid = u.objectGuid, 
        msExchMailboxGuid = u.msExchMailboxGuid, 
        CompanyName = u.CompanyName, 
        ResellerOU = u.ResellerOU, 
        DisplayName = u.DisplayName, 
        MBXServer = u.MBXServer, 
        MBXSG = u.MBXSG, 
        MBXDB = u.MBXDB, 
        MBXWarningLimit = u.MBXWarningLimit, 
        MBXSendLimit = u.MBXSendLimit, 
        MBXSendReceiveLimit = u.MBXSendReceiveLimit, 
        extensionAttribute10 = u.extensionAttribute10, 
        legacyExchangeDN = u.legacyExchangeDN, 
        UserPrincipalName = u.UserPrincipalName, 
        Mail = u.Mail, 
        lastLogonTimeStamp = u.lastLogonTimestamp, 
        createTimeStamp = u.createTimeStamp, 
        modifyTimeStamp = u.modifyTimeStamp, 
        altRecipient = u.altRecipient, 
        altRecipientBL = u.altRecipientBL, 
        DeletedDate = u.DeletedDate, 
        MailboxGuid = us.MailboxGuid, 
        Date = us.Date, 
        AssociatedItemCount = us.AssociatedItemCount, 
        DeletedItemCount = us.DeletedItemCount, 
        ItemCount = us.ItemCount, 
        LastLoggedOnUserAccount = us.LastLoggedOnUserAccount, 
        LastLogonTime = us.LastLogonTime, 
        StorageLimitStatus = us.StorageLimitStatus, 
        TotalDeletedItemSize = us.TotalDeletedItemSize, 
        TotalItemSize = us.TotalItemSize, 
        MailboxDatabase = us.MailboxDatabase 
       }) 
      .Join(Context.TechContacts,   // Table to Join 
       u => u.UserPrincipalName,  // Column to Join From 
       tc => tc.UPN,     // Column to Join To 
       (u, tc) => new     // Declare Final Column Names 
       { 
        ObjectGuid = u.ObjectGuid, 
        msExchMailboxGuid = u.msExchMailboxGuid, 
        CompanyName = u.CompanyName, 
        ResellerOU = u.ResellerOU, 
        DisplayName = u.DisplayName, 
        MBXServer = u.MBXServer, 
        MBXSG = u.MBXSG, 
        MBXDB = u.MBXDB, 
        MBXWarningLimit = u.MBXWarningLimit, 
        MBXSendLimit = u.MBXSendLimit, 
        MBXSendReceiveLimit = u.MBXSendReceiveLimit, 
        extensionAttribute10 = u.extensionAttribute10, 
        legacyExchangeDN = u.legacyExchangeDN, 
        UserPrincipalName = u.UserPrincipalName, 
        Mail = u.Mail, 
        lastLogonTimeStamp = u.lastLogonTimeStamp, 
        createTimeStamp = u.createTimeStamp, 
        modifyTimeStamp = u.modifyTimeStamp, 
        altRecipient = u.altRecipient, 
        altRecipientBL = u.altRecipientBL, 
        DeletedDate = u.DeletedDate, 
        MailboxGuid = u.MailboxGuid, 
        Date = u.Date, 
        AssociatedItemCount = u.AssociatedItemCount, 
        DeletedItemCount = u.DeletedItemCount, 
        ItemCount = u.ItemCount, 
        LastLoggedOnUserAccount = u.LastLoggedOnUserAccount, 
        LastLogonTime = u.LastLogonTime, 
        StorageLimitStatus = u.StorageLimitStatus, 
        TotalDeletedItemSize = u.TotalDeletedItemSize, 
        TotalItemSize = u.TotalItemSize, 
        MailboxDatabase = u.MailboxDatabase, 
        // New Columns from this join 
        UPN = tc.UPN, 
        Customer_TechContact = tc.Customer_TechContact, 
        Customer_TechContactEmail = tc.Customer_TechContactEmail, 
        Reseller_TechContact = tc.Reseller_TechContact, 
        Reseller_TechContactEmail = tc.Reseller_TechContact, 
        Reseller_Name = tc.Reseller_Name 
       }) 
      .Where(u => true) 
      .OrderBy(GlobalVars.SortColumn + " " + GlobalVars.SortDirection) 
      .Select("New(" + Fields + ")"); 

     // Add Extra Filters 
     if (!(string.IsNullOrWhiteSpace(SearchCompanyNameTextBox.Text))) 
     { 
      Query = Query.Where("CompanyName.StartsWith(@0)", SearchCompanyNameTextBox.Text); 
     } 

     // Set the Record Count 
     GlobalVars.TotalRecords = Query.Count(); 

     // Add Paging 
     Query = Query 
      .Skip(GlobalVars.Skip) 
      .Take(GlobalVars.Take); 

     // GridView Datasource Binding 
     GridViewMailboxes.DataSource = Query; 
     GridViewMailboxes.DataBind(); 
    } 
} 

Questo è ciò che SQL viene eseguito in background:

SELECT TOP (20) 
[Project1].[C1] AS [C1], 
[Project1].[objectGuid] AS [objectGuid], 
[Project1].[msExchMailboxGuid] AS [msExchMailboxGuid], 
[Project1].[CompanyName] AS [CompanyName], 
[Project1].[ResellerOU] AS [ResellerOU], 
[Project1].[DisplayName] AS [DisplayName], 
[Project1].[MBXServer] AS [MBXServer], 
[Project1].[MBXSG] AS [MBXSG], 
[Project1].[MBXDB] AS [MBXDB], 
[Project1].[MBXWarningLimit] AS [MBXWarningLimit], 
[Project1].[MBXSendLimit] AS [MBXSendLimit], 
[Project1].[MBXSendReceiveLimit] AS [MBXSendReceiveLimit], 
[Project1].[extensionAttribute10] AS [extensionAttribute10], 
[Project1].[legacyExchangeDN] AS [legacyExchangeDN], 
[Project1].[UserPrincipalName] AS [UserPrincipalName], 
[Project1].[Mail] AS [Mail], 
[Project1].[lastLogonTimestamp] AS [lastLogonTimestamp], 
[Project1].[createTimeStamp] AS [createTimeStamp], 
[Project1].[modifyTimeStamp] AS [modifyTimeStamp], 
[Project1].[altRecipient] AS [altRecipient], 
[Project1].[altRecipientBL] AS [altRecipientBL], 
[Project1].[DeletedDate] AS [DeletedDate] 
    FROM (SELECT [Project1].[objectGuid] AS [objectGuid], 
     [Project1].[msExchMailboxGuid] AS [msExchMailboxGuid], 
     [Project1].[CompanyName] AS [CompanyName], 
     [Project1].[ResellerOU] AS [ResellerOU], 
     [Project1].[DisplayName] AS [DisplayName], 
     [Project1].[MBXServer] AS [MBXServer], 
     [Project1].[MBXSG] AS [MBXSG], 
     [Project1].[MBXDB] AS [MBXDB], 
     [Project1].[MBXWarningLimit] AS [MBXWarningLimit], 
     [Project1].[MBXSendLimit] AS [MBXSendLimit], 
     [Project1].[MBXSendReceiveLimit] AS [MBXSendReceiveLimit], 
     [Project1].[extensionAttribute10] AS [extensionAttribute10], 
     [Project1].[legacyExchangeDN] AS [legacyExchangeDN], 
     [Project1].[UserPrincipalName] AS [UserPrincipalName], 
     [Project1].[Mail] AS [Mail], 
     [Project1].[lastLogonTimestamp] AS [lastLogonTimestamp], 
     [Project1].[createTimeStamp] AS [createTimeStamp], 
     [Project1].[modifyTimeStamp] AS [modifyTimeStamp], 
     [Project1].[altRecipient] AS [altRecipient], 
     [Project1].[altRecipientBL] AS [altRecipientBL], 
     [Project1].[DeletedDate] AS [DeletedDate], 
     [Project1].[C1] AS [C1], 
     row_number() OVER (ORDER BY [Project1].[CompanyName] ASC) AS [row_number] 
      FROM (SELECT 
       [Extent1].[objectGuid] AS [objectGuid], 
       [Extent1].[msExchMailboxGuid] AS [msExchMailboxGuid], 
       [Extent1].[CompanyName] AS [CompanyName], 
       [Extent1].[ResellerOU] AS [ResellerOU], 
       [Extent1].[DisplayName] AS [DisplayName], 
       [Extent1].[MBXServer] AS [MBXServer], 
       [Extent1].[MBXSG] AS [MBXSG], 
       [Extent1].[MBXDB] AS [MBXDB], 
       [Extent1].[MBXWarningLimit] AS [MBXWarningLimit], 
       [Extent1].[MBXSendLimit] AS [MBXSendLimit], 
       [Extent1].[MBXSendReceiveLimit] AS [MBXSendReceiveLimit], 
       [Extent1].[extensionAttribute10] AS [extensionAttribute10], 
       [Extent1].[legacyExchangeDN] AS [legacyExchangeDN], 
       [Extent1].[UserPrincipalName] AS [UserPrincipalName], 
       [Extent1].[Mail] AS [Mail], 
       [Extent1].[lastLogonTimestamp] AS [lastLogonTimestamp], 
       [Extent1].[createTimeStamp] AS [createTimeStamp], 
       [Extent1].[modifyTimeStamp] AS [modifyTimeStamp], 
       [Extent1].[altRecipient] AS [altRecipient], 
       [Extent1].[altRecipientBL] AS [altRecipientBL], 
       [Extent1].[DeletedDate] AS [DeletedDate], 
       1 AS [C1] 
       FROM [dbo].[Users] AS [Extent1] 
       INNER JOIN [dbo].[UserStats] AS [Extent2] ON [Extent1].[msExchMailboxGuid] = [Extent2].[MailboxGuid] 
       INNER JOIN [dbo].[TechContacts] AS [Extent3] ON [Extent1].[UserPrincipalName] = [Extent3].[UPN] 
      ) AS [Project1] 
    ) AS [Project1] 
WHERE [Project1].[row_number] > 120 
ORDER BY [Project1].[CompanyName] ASC 
+0

Cosa intendi quando dici * Non penso che il mio join funzioni bene *? Sta restituendo i record corretti? È lento? Hai visto lo sql generato? – Aducci

+0

Normalmente quando mi unisco in questo modo, posso usare il nome alias della tabella per restituire i record che voglio. f.ex se l'ho chiamato come nella mia istruzione SQL posso usare u.Field1, u.Field2 per tirare indietro i record dalla tabella Users che ho aliasato come u. Se utilizzo la mia query in questo modo, devo riportare il campo con u.u.FieldName. Questo non mi sembra giusto! Vedi la mia dichiarazione .OrderBy per vedere cosa intendo. – HungryHippos

+0

Se funziona e non è lento, non capisco cosa stai cercando.Non sembra esserci un problema reale. – Aducci

risposta

2

Non c'è molto di una risposta, ma un consiglio. Per prima cosa, prendi lo LinqPad. Quando si esegue il tuning delle query, è inestimabile. In secondo luogo, la mia scommessa è che stai ricevendo una query enorme a seguito dell'uso di .Join. Linq2Entities ha la brutta abitudine di creare proiezioni (sottoquery) ogni volta che si fa un join. Passerei un po 'di tempo con LinqPad e la mia query fino a quando non avrò ottenuto la query desiderata.

+0

grazie, avremo un gioco con LinqPad e vedremo cosa è cosa :) – HungryHippos

+0

Oh uomo, questo diventa più divertente. Aggiornerò il mio OP se posso con quello che ho attualmente. – HungryHippos

+0

OK, quindi ho giocato con LinqPad ma per me non è più semplice, perché non ci sono funzioni interessanti come il completamento automatico, quindi non ho idea se quello che sto digitando funzioni effettivamente. Se si controlla il mio OP sopra, si vedrà quello che sono attualmente in esecuzione, ma è notevolmente più lento dei miei attuali metodi TableAdapter e Stored Proc. – HungryHippos

Problemi correlati