A consulta complexa do Linq não está funcionando conforme o esperado
Quero combinar resultados de 4 tabelas e selecionar campos específicos usando o LINQ. Por favor, tenha paciência comigo, pois eu não fiz consultas LINQ complexas.
Tabela 1 - Assinante
Tabela 2 - Assinatura
Tabela 3 - Estado
Tabela 4 - País
NOTA: Um assinante pode ter 0, 1 ou muitas assinaturas. Isso significa que uma chave estrangeira (SubscriberID) faz parte da tabela Assinatura
A consulta deve retornar todos os assinantes da tabela de assinantes uma vez. Se o assinante tem uma assinatura ou não, isso não importa. Eu preciso ter todos os meus assinantes na lista de resultados.
Aqui é onde fica complicado:
Na lista de resultados, desejo incluir uma propriedade 'PubName'. Essa propriedade é uma sequência separada por vírgula com os nomes dos pub nos quais o assinante está inscrito. O PubName é uma coluna na tabela Assinatura.
Eu escrevi um procedimento armazenado no SQL usando uma função adicional para construir o campo PubName por assinante.
Por exemplo: nossa lista possui 3 linhas:
Victor, 123 W 45th st # 43, Nova York, NY, 'Mag A, Mag B, Mag C'(Victor está inscrito nas revistas Mag A, B e C)
Dan, 564 E 23rd st FL3, Nova York, NY, 'Mag A, Mag D, Mag F'(Dan está inscrito nas revistas Mag A, D e F)
Nicole, 78 E 12rd st # 3, Nova York, NY, 'NULL'(Nicole não tem assinaturas)
var model = await (
from subscriber in db.Subscribers
// left join
from state in db.States.Where(s => s.State_ID == subscriber.SubscriberState_ID).DefaultIfEmpty()
// left join
from country in db.Countries.Where(s => s.Country_ID == subscriber.SubscriberCountry_ID).DefaultIfEmpty()
orderby subscriber.Subscriber_ID descending
select new SubscriberGridViewModel
{
Subscriber_ID = subscriber.Subscriber_ID,
Pub = GetPubName(subscriber.Subscriber_ID).ToString(),
FirstName = subscriber.SubscriberFirstName,
LastName = subscriber.SubscriberLastName,
Address1 = subscriber.SubscriberAddress1,
Address2 = subscriber.SubscriberAddress2,
Email = subscriber.SubscriberEmail,
Organization = subscriber.SubscriberOrganizationName,
Phone = subscriber.SubscriberPhone,
Zip = subscriber.SubscriberZipcode
}).ToListAsync();
private static string GetPubName(int? subscriber_id)
{
string pubs = string.Empty;
try
{
var db = new CirculationEntities();
var model = db.Subscriptions.Where(s => s.Subscriber_ID == subscriber_id).ToList();
foreach(Subscription sub in model)
{
if (string.IsNullOrEmpty(pubs))
pubs = sub.SubscriptionPublication;
else
pubs = ", " + sub.SubscriptionPublication;
}
return pubs;
}
catch
{
return "EMPTY";
}
}
com o código a seguir, estou recebendo esse erro:
"O LINQ to Entities não reconhece o método 'System.String GetPubName (System.Nullable`1 [System.Int32])' ', e esse método não pode ser convertido em uma expressão de armazenamento."
Eu entendo o erro. Um método não pode ser convertido em expressão de loja dentro de uma declaração LINQ.
É possível conseguir isso no LINQ? Se sim, alguém pode me mostrar como? Não consigo encontrar uma solução.FIGURADO COMO CONCATENAR A CORDA:
var query = from subscription in db.Subscriptions.ToList()
group subscription by subscription.Subscriber_ID into g
select new
{
Subscriber_ID = g.Key,
Pub = string.Join(", ", g.Select(x => x.SubscriptionPublication).Distinct())
};
var model = (from s in query
join subscriber in db.Subscribers on s.Subscriber_ID equals subscriber.Subscriber_ID
join state in db.States on subscriber.SubscriberState_ID equals state.State_ID
join country in db.Countries on subscriber.SubscriberCountry_ID equals country.Country_ID
select new SubscriberGridViewModel
{
Subscriber_ID = subscriber.Subscriber_ID,
Pub = s.Pub,
FirstName = subscriber.SubscriberFirstName,
LastName = subscriber.SubscriberLastName,
Address1 = subscriber.SubscriberAddress1,
Address2 = subscriber.SubscriberAddress2,
Email = subscriber.SubscriberEmail,
Organization = subscriber.SubscriberOrganizationName,
Phone = subscriber.SubscriberPhone,
City = subscriber.SubscriberCity,
State = (subscriber.SubscriberState_ID == 54) ? subscriber.SubscriberState : state.StateName,
StateAbbv = (subscriber.SubscriberState_ID == 54) ? subscriber.SubscriberState : state.StateAbbreviation,
Country = country.CountryName,
Zip = subscriber.SubscriberZipcode
}).ToList();
Os resultados não incluem assinantes sem assinaturas. Alguma idéia de como consertar isso?