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
¿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
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
Si funciona y no es lento, no entiendo lo que está buscando.No parece haber un problema real – Aducci