2012-03-08 10 views
5

Lurker de larga duración, primer póster. ¡He encontrado algunas buenas respuestas aquí en el pasado así que imagino que iría aquí y vería si puedo obtener un poco de ayuda!Uniones múltiples en la consulta de Entity Framework

Soy bastante nuevo en Linq y estoy utilizando Entity Framework para mi objeto. Tengo un archivo .edmx en mi proyecto.

En primer lugar me importó el uso de la clase System.Linq.Dynamic de las páginas de muestra que vienen con VS 2010, por lo que puede agregar esto en mi página:

usando System.Linq.Dynamic;

El problema es que no creo que mi unión funcione bien.

Este es mi código actual:

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

Como puedo escribirlo por lo que funciona como este en SQL normal?

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 

necesito mantener las cláusulas .Where dinámicos y nombres de campo .SELECT, el problema como se puede ver en este momento es que necesito hacer uuCompanyName para volver al campo u.CompanyName ya que está en mi se une dos veces.

He buscado en Google esto por un tiempo pero aún no he dicho ningún dado.

Cualquier ayuda muy apreciada!

EDITAR - esta es mi consulta actual. Funciona, pero es una pesadilla para la vista.

Tener conmigo. Quería incluir todo aquí si puedo, incluso si es un poco demasiado.

La selección de columna dinámica es imprescindible para mí. De lo contrario, también podría seguir con mis adaptadores de mesa y procs almacenados. Ser capaz de reducir mi consulta para devolver menos datos es uno de mis objetivos con esto. Si alguien puede sugerir mejoras, ¿soy todo oídos?

No pude encontrar una manera de dejar de tener que seleccionar mis uniones en los subelementos, en SQL cuando me uno, simplemente tengo que devolver las columnas que quiero a través de mi instrucción 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(); 
    } 
} 

Esto es lo que se ejecuta en segundo plano SQL:

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

¿Qué quieres decir cuando dices * No creo que mi unión esté funcionando bien *? ¿Devuelve los registros correctos? ¿Es lento? ¿Has visto el sql generado? – Aducci

+0

Normalmente cuando me uno de esta manera, puedo usar el nombre de alias de la tabla para devolver los registros que quiero. f.ex si lo llamé como en mi declaración de SQL, puedo usar u.Field1, u.Field2 para recuperar registros de la tabla de Usuarios a los que he asignado un alias como u. Si utilizo mi consulta de esta manera, tengo que retirar el campo con u.u.FieldName. ¡Esto no me parece correcto! Ver mi declaración .OrderBy para ver a qué me refiero. – HungryHippos

+0

Si funciona y no es lento, no entiendo lo que está buscando.No parece haber un problema real – Aducci

Respuesta

2

No hay mucho de una respuesta, pero el consejo. Primero, ve a tomar el LinqPad. Al hacer ajuste de consulta, es invaluable. En segundo lugar, mi apuesta es que recibirá una gran consulta como resultado de usar .Join. Linq2Entities tiene la desagradable costumbre de crear proyecciones (subconsultas) cada vez que se une. Pasaría algún tiempo de calidad con LinqPad y mi consulta hasta que obtenga la consulta que quiero.

+0

gracias, tendrá un juego con LinqPad y verá qué es lo que :) – HungryHippos

+0

Oh, hombre esto se vuelve más divertido. Actualizaré mi OP si puedo con lo que tengo actualmente. – HungryHippos

+0

OK, así que he jugado con LinqPad, pero no es realmente más fácil para mí, ya que no hay funciones geniales como autocompletar, así que no tengo idea de si lo que estoy escribiendo está realmente funcionando. Si revisas mi OP arriba, verás lo que estoy ejecutando actualmente, pero es notablemente más lento que mis métodos TableAdapter y Stored Proc actuales. – HungryHippos

Cuestiones relacionadas