He estado usando Saltee() y .Tomar() los métodos de extensión con LINQ a SQL desde hace un tiempo, sin problemas, pero en todos los casos los he usado siempre lo ha sido durante una sola tabla - tales como:LINQ To SQL Paging
database.Users.Select(c => c).Skip(10).Take(10);
Mi problema es que ahora estoy proyectando un conjunto de resultados de varias tablas y quiero página en el conjunto global (y aún así obtener el beneficio de paginación en el DB) .
Mi modelo de entidad es el siguiente:
Una campaña [tiene muchos] grupos, un grupo [tiene muchos] contactos
esto se modela a través de una relación en la base de datos como
Campaña -> CampaignToGroupMapping -> Grupo -> GroupToContactMapping -> Contacto
Necesito generar una estructura de datos ho lding los detalles de una campaña y también una lista de cada contacto asociado a la campaña a través de la CampaignToGroupMapping, es decir,
Campaign
CampaignName
CampaignFrom
CampaignDate
Recipients
Recipient 1
Recipient 2
Recipient n...
que había tratado de escribir una consulta LINQ utilizando .SelectMany para proyectar el conjunto de contactos de cada grupo en un conjunto de datos lineales, con la esperanza de que pueda .Skip() .Take() de eso.
Mi intento fue:
var schedule = (from c in database.Campaigns
where c.ID == highestPriority.CampaignID
select new PieceOfCampaignSchedule
{
ID = c.ID,
UserID = c.UserID,
Name = c.Name,
Recipients = c.CampaignGroupsMappings.SelectMany(d => d.ContactGroup.ContactGroupMappings.Select(e => new ContactData() { /*Contact Data*/ }).Skip(c.TotalSent).Take(totalRequired)).ToList()
}).SingleOrDefault();
El problema es que la paginación (en lo que respecta a Skip() y Take()) está sucediendo para cada grupo, no a todo el conjunto de datos.
Esto significa que si utilizo el valor 200 para el parámetro totalRequired (pasado a .Tomar()) y tengo 3 grupos asociados con esta campaña, se tardará 200 de cada grupo - no 200 del total de datos de cada grupo asociado con la campaña.
En SQL, que podría lograr esto con una consulta como:
select * from
(
select [t1].EmailAddress, ROW_NUMBER() over(order by CampaignID desc) as [RowNumber] from contacts as [t1]
inner join contactgroupmapping as [t2] on [t1].ID = [t2].ContactID
inner join campaigngroupsmapping as [t3] on [t3].ContactGroupID = [t2].GroupID
where [t3].CampaignID = @HighestPriorityCampaignID
) as [Results] where [Results].[RowNumber] between 500 and 3000
Con esta consulta, estoy de paginación sobre el conjunto combinado de contactos de cada grupo asociado con la campaña en particular. Entonces mi pregunta es, ¿cómo puedo lograr esto usando la sintaxis de LINQ To SQL?
Idealmente, estaba buscando una solución que solo utilizara LINQ To SQL. Como mencioné en mi respuesta, podría ejecutar la consulta SQL directamente desde ADO.NET también, pero quería usar LINQ To SQL para coherencia con otro código. Gracias por la sugerencia. – Martin
LINQ to SQL admite vistas. Simplemente arrástralas y sujétalas al diseñador. Entendí que querrías una solución LINQ to SQL. Te sugerí que crees una vista para usar. por el marco de LINQ to SQL. – rguerreiro