I want to combine results from 4 tables and select specific fields using LINQ. Please bear with me since I have not done complex LINQ queries.
Table 1 - Subscriber
Table 2 - Subscription
Table 3 - State
Table 4 - Country
NOTE: A subscriber can have 0, 1, or many subscriptions. This means a foreign key (SubscriberID) is part of the Subscription table
The query should return every subscriber from the subscriber table once. Whether the subscriber has a subscription or not it does not matter. I need to have all of my subscribers in the result list.
Here is where it gets complicated:
In the result list I want to include a property 'PubName'. This property is a comma separated string with the pub names that the subscriber is subscribed to. The PubName is a column in the Subscription table.
I have written a Stored Procedure in SQL using an additional function to construct the PubName field per subscriber.
For Example: our list has 3 rows:
- Victor, 123 W 45th st #43, New York, NY, 'Mag A, Mag B, Mag C'
(Victor is subscribed to Mag A, B,and C)
- Dan, 564 E 23rd st FL3, New York, NY, 'Mag A, Mag D, Mag F'
(Dan is subscribed to Mag A, D,and F)
- Nicole, 78 E 12rd st #3, New York, NY, 'NULL'
(Nicole has no subscriptions)
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";
}
}
with the following code I am getting this error:
"LINQ to Entities does not recognize the method 'System.String GetPubName(System.Nullable`1[System.Int32])' method, and this method cannot be translated into a store expression."
I understand the error. A method cannot be translated into store expression inside a LINQ statment.
- Is it possible to achieve this in LINQ? If so, can someone show me how? I am unable to find a solution.
FIGURED OUT HOW TO CONCATENATE THE STRING:
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();
The results is not including subscribers without subscriptions. Any ideas how to fix it?