How can I make a nested projection in a Linq query when using the group by clause? - sql

I'm trying to work with grouped data coming back from SQL.
The method I'm writing is to provide the data for a "Case Status Overview" screen.
It must produce a nested XML document.
Now, I could do it the easy way, but I'm trying to learn whether it's possible to use the linq "group by" statement and then to project the data already nested. (the easy way would be just to pull back the data in a tabular fashion from the database and then for-loop through it forming the Xml document for output)
Here is the data hierarchy:
Every Case has a DebtType and every DebtType has a Client.
Here is the SQL that retrieves the data:
SELECT ClientNames.ClientID ,
ClientNames.ClientCode ,
ClientNames.ClientName ,
DebtTypes.DebtTypeID ,
DebtTypes.DebtTypeShortDesc ,
DebtTypes.DebtTypeLongDesc ,
Cases.CurrentStateCode ,
SUM(1 - CAST(Cases.CaseClosed AS INT)) AS OpenCaseCount ,
SUM(CAST(Cases.CaseClosed AS INT)) AS ClosedCaseCount ,
SUM(CAST(Cases.CaseOnHold AS INT)) AS OnHoldCaseCount ,
SUM(CAST(Cases.CaseReferred AS INT)) AS ReferredCaseCount ,
COUNT(Cases.CaseID) AS TotalCaseCount ,
SUM(Cases.CaseTotalPaid) AS TotalAmountPaid ,
SUM(Cases.CaseCurrentOutstandingAmount) AS TotalAmountOutstanding,
SUM(Cases.CaseTotalDebtWrittenOff) AS TotalAmountWrittenOff ,
SUM(Cases.CaseTotalDebtCancelled) AS TotalAmountCancelled
FROM ClientNames
INNER JOIN ClientDebtTypes
ON ClientNames.ClientID = ClientDebtTypes.ClientID
INNER JOIN DebtTypes
ON ClientDebtTypes.DebtTypeID = DebtTypes.DebtTypeID
INNER JOIN Cases
ON ClientDebtTypes.ClientDebtTypeID = Cases.CaseClientDebtTypeID
GROUP BY ClientNames.ClientID ,
ClientNames.ClientCode ,
ClientNames.ClientName ,
DebtTypes.DebtTypeID ,
DebtTypes.DebtTypeShortDesc,
DebtTypes.DebtTypeLongDesc ,
Cases.CurrentStateCode
ORDER BY ClientNames.ClientID,
DebtTypes.DebtTypeID,
CurrentStateCode
Using Linqer it converts it to:
from clientnames in db.ClientNames
join clientdebttypes in db.ClientDebtTypes on clientnames.ClientID equals clientdebttypes.ClientID
join debttypes in db.DebtTypes on clientdebttypes.DebtTypeID equals debttypes.DebtTypeID
join cases in db.Cases on new { ClientDebtTypeID = clientdebttypes.ClientDebtTypeID } equals new { ClientDebtTypeID = cases.CaseClientDebtTypeID }
group new {clientnames, debttypes, cases} by new {
clientnames.ClientID,
clientnames.ClientCode,
clientnames.ClientName1,
debttypes.DebtTypeID,
debttypes.DebtTypeShortDesc,
debttypes.DebtTypeLongDesc,
cases.CurrentStateCode
} into g
orderby
g.Key.ClientID,
g.Key.DebtTypeID,
g.Key.CurrentStateCode
select new {
ClientID = (System.Int32?)g.Key.ClientID,
g.Key.ClientCode,
g.Key.ClientName1,
DebtTypeID = (System.Int32?)g.Key.DebtTypeID,
g.Key.DebtTypeShortDesc,
g.Key.DebtTypeLongDesc,
g.Key.CurrentStateCode,
OpenCaseCount = (System.Int64?)g.Sum(p => 1 - Convert.ToInt32(p.cases.CaseClosed)),
ClosedCaseCount = (Int32?)g.Sum(p => Convert.ToInt32(p.cases.CaseClosed)),
OnHoldCaseCount = (Int32?)g.Sum(p => Convert.ToInt32(p.cases.CaseOnHold)),
ReferredCaseCount = (Int32?)g.Sum(p => Convert.ToInt32(p.cases.CaseReferred)),
TotalCaseCount = (Int64?)g.Count(p => p.cases.CaseID != null),
TotalAmountPaid = (System.Decimal?)g.Sum(p => p.cases.CaseTotalPaid),
TotalAmountOutstanding = (System.Decimal?)g.Sum(p => p.cases.CaseCurrentOutstandingAmount),
TotalAmountWrittenOff = (System.Decimal?)g.Sum(p => p.cases.CaseTotalDebtWrittenOff),
TotalAmountCancelled = (System.Decimal?)g.Sum(p => p.cases.CaseTotalDebtCancelled)
}
Now as I mentioned, I could stop there and right a for loop to create the Xml data.
But I'm trying to create a nested group (IGrouping<ClientName,IGrouping<DebtType,SummaryClass>>)
and then project the data in a nested format.
Now we're using LinqToXsd to create strong type wrappers for out Xml documents, but essentially all this means is that out output type is:
private class ClientSummary
{
public string ClientName { get; set; }
public IList<DebtTypeSummary> DebtTypes { get; set; }
}
private class DebtTypeSummary
{
public string DebtType { get; set; }
public IList<StateCodeSummary> StateCodes { get; set; }
}
private class StateCodeSummary
{
public string StateCode { get; set; }
public int TotalCount { get; set; }
public decimal TotalAmountPaid { get; set; }
//etc
//etc
//etc
}
Now I got as far as writing the following Linq:
var grouping = from cases in db.Cases
join clientdebttypes in db.ClientDebtTypes on cases.CaseClientDebtTypeID equals clientdebttypes.ClientID
join debttypes in db.DebtTypes on clientdebttypes.DebtTypeID equals debttypes.DebtTypeID
group cases by new ClientDebtTypePair() { ClientDebtType = clientdebttypes, DebtType = debttypes } into casesByClientDebtTypes
join clientnames in db.ClientNames on casesByClientDebtTypes.Key.ClientDebtType.ClientName equals clientnames
group casesByClientDebtTypes by clientnames;
var projected = from casesByClientDebtTypes in grouping
let client = casesByClientDebtTypes.Key
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType()
{
Client = new Client()
{
ClientID = client.ClientID,
DisplayName = client.ClientName1,
},
DebtTypes = from cases in casesByClientDebtTypes
let debttype = cases.Key.DebtType
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType.DebtTypesLocalType()
{
DebtType = new DebtType()
{
DebtTypeID = debttype.DebtTypeID,
Description = debttype.DebtTypeLongDesc,
DisplayName = debttype.DebtTypeShortDesc,
},
StatesCodes = from cases2 in cases
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType.DebtTypesLocalType.StatesCodesLocalType()
{
ClosedCasesCount = cases2.Sum(p => Convert.ToInt32(p.cases.CaseClosed))
which joins and groups the database tables and then tries to project the result a ClientSummary (the class names are different but that's because the above is a simplified view of the output classes). I fail completely when I've drilled all the way down to the Cases table and I find that I don't really understand how to do agregate functions. They appear to only be available on IGrouping<K, T>s and it seems I've just got confused.
I need to also ensure that the summaries are calculated server side, pulling back millions of cases would be bad.
Can anybody help me with this one? Is this even possible?
Regards,
James.
-------### UPDATE 1 ###-------
OK, been working on this again today.
I decided to use Linq2SQL to pull pack 2D data and then reformat it using Linq2Objects.
Here is what I started with:
var sql = from clientnames in db.ClientNames
join clientdebttypes in db.ClientDebtTypes on clientnames.ClientID equals clientdebttypes.ClientID
join debttypes in db.DebtTypes on clientdebttypes.DebtTypeID equals debttypes.DebtTypeID
join cases in db.Cases on new { ClientDebtTypeID = clientdebttypes.ClientDebtTypeID } equals new { ClientDebtTypeID = cases.CaseClientDebtTypeID }
group new { clientnames, debttypes, cases } by new
{
clientnames.ClientID,
clientnames.ClientCode,
clientnames.ClientName1,
debttypes.DebtTypeID,
debttypes.DebtTypeShortDesc,
debttypes.DebtTypeLongDesc,
cases.CurrentStateCode
} into g
orderby
g.Key.ClientID,
g.Key.DebtTypeID,
g.Key.CurrentStateCode
select new
{
Client = new Client{ ClientID = g.Key.ClientID, DisplayName = g.Key.ClientName1 },
DebtType = new DebtType{ DebtTypeID = g.Key.DebtTypeID, DisplayName = g.Key.DebtTypeShortDesc, Description = g.Key.DebtTypeLongDesc },
StateSummary = new LoadCaseStatusOverviewScreenOutput.ClientsLocalType.DebtTypesLocalType.StatesCodesLocalType()
{
StateCode = g.Key.CurrentStateCode,
OpenCasesCount = g.Sum(p => 1 - Convert.ToInt32(p.cases.CaseClosed)),
ClosedCasesCount = g.Sum(p => Convert.ToInt32(p.cases.CaseClosed)),
OnHoldCasesCount = g.Sum(p => Convert.ToInt32(p.cases.CaseOnHold)),
ReferredCasesCount = g.Sum(p => Convert.ToInt32(p.cases.CaseReferred)),
TotalCasesCount = g.Count(p => p.cases.CaseID != null),
TotalAmountPaid = g.Sum(p => p.cases.CaseTotalPaid),
TotalAmountOutstanding = g.Sum(p => p.cases.CaseCurrentOutstandingAmount),
TotalAmountWrittenOff = g.Sum(p => p.cases.CaseTotalDebtWrittenOff),
TotalAmountCancelled = g.Sum(p => p.cases.CaseTotalDebtCancelled),
}
};
var res = sql.ToList();
output.Clients = (from results in res
group results by results.Client into resultsByClient
from resultsByDebtType in
(from results in resultsByClient
group results by results.DebtType)
group resultsByDebtType by resultsByClient.Key into resultsByDebtTypeByClient
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType()
{
Client = resultsByDebtTypeByClient.Key,
DebtTypes = (from resultsByDebtType in resultsByDebtTypeByClient
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType.DebtTypesLocalType()
{
DebtType = resultsByDebtType.Key,
StatesCodes = (from results in resultsByDebtType
let summary = results.StateSummary
select results.StateSummary).ToList()
}).ToList()
}).ToList();
That runs, but produces one Client/DebtType/Summary set for every result. So even though there is only one client in this case, I end up with 1300 clients, all identical.
I simplified it to the following:
output.Clients = (from results in res
group results by results.Client into resultsByClient
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType()
{
Client = resultsByClient.Key,
DebtTypes = null,
}).ToList();
That produces 1300 clients. Next I tried this:
output.Clients = (from results in res
group results by results.Client.ClientID into resultsByClient
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType()
{
Client = new Client { ClientID = resultsByClient.Key },
DebtTypes = null,
}).ToList();
And THAT produces ONE client (hurray!). Except I loose all the client information (boo!)
Guessing that as it's comparing client by refernce instead of by content I wrote the following:
public partial class Client
{
public static bool operator ==(Client left, Client right)
{
return left.ClientID == right.ClientID;
}
public static bool operator !=(Client left, Client right)
{
return left.ClientID != right.ClientID;
}
public override int GetHashCode()
{
return ClientID;
}
}
That did nothing. It repeatedly calls GetHashCode(), which I fudged to force it to return the same hash code for any matching ClientID, but it still created 1300 Client groups.
Regards,
James.
-------### UPDATE 2 ###-------
OK, I thought I would have a go at making the Linq2Sql output only simple values for grouping by:
g.Key.ClientID,
g.Key.ClientName1,
g.Key.DebtTypeID,
g.Key.DebtTypeShortDesc,
g.Key.DebtTypeLongDesc,
And then changed the test Linq2Objects to:
output.Clients = (from results in res
group results by new { ClientID = results.ClientID, DisplayName = results.ClientName1 } into resultsByClient
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType()
{
Client = new Client { ClientID = resultsByClient.Key.ClientID, DisplayName = resultsByClient.Key.DisplayName },
DebtTypes = null,
}).ToList();
That works. So anonymous types compare in the way I want them to, by content not reference (apparently)
This does not:
output.Clients = (from results in res
group results by new SiDemClient { ClientID = results.ClientID, DisplayName = results.ClientName1 } into resultsByClient
select new LoadCaseStatusOverviewScreenOutput.ClientsLocalType()
{
Client = resultsByClient.Key,//new Client { ClientID = resultsByClient.Key.ClientID, DisplayName = resultsByClient.Key.DisplayName },
DebtTypes = null,
}).ToList();
That still creates 1300 groups.
So, anonymous types compare in a magical way that I don't understand. How can I make my Client class compare like an anonymous type?
Regards,
James.
-------### SOLUTION FOUND ###-------
-------### MANY THANKS TO Enigmativity ###-------
I needed to override the Equals() method instead of implementing the == operator.
Now the grouping works and I have a wonderful Xml document to reutrn!
public partial class SiDemClient
{
public override bool Equals(object obj)
{
if (obj is SiDemClient)
{
return this.ClientID.Equals(((SiDemClient)obj).ClientID);
}
return false;
}
public override int GetHashCode()
{
return ClientID;
}
}
Many Thanks,
James.

When you override GetHashCode you must also override Equals. The == & != operators are irrelevant.
Try with this:
public partial class Client
{
public override bool Equals(object obj)
{
if (obj is Client)
{
return this.ClientID.Equals(((Client)obj).ClientID);
}
return false;
}
public override int GetHashCode()
{
return this.ClientID.GetHashCode();
}
}
See if that helps.

Related

Im using datatable in my project mvc , i want display Categorie name in place of categorye id foreign key in table courses

[HttpGet]
public JsonResult GetData()
{``
ApplicationDbContext db = new ApplicationDbContext();
var course = db.Courses
.Include(d=>d.Competences)
.Include(d=>d.Sequences)
.ToList().Select(p => new { Id = p.Id, Titre = p.Titre, ShortDescription = p.ShortDescription, Price = p.Price, CategorieId = p.CategorieId });
var query = from q in db.Courses
join cat in db.Categories.AsEnumerable()
on q.CategorieId equals cat.Libelle
enter code here
return Json(new { data = course },
JsonRequestBehavior.AllowGet);
}

datediff with case statement in select query linq

select case statement in linq query.
Here is the query on sql:
select case when DATEDIFF(day,convert(varchar,Min([Order].CreatedOnUtc),101),convert(varchar,Max([Order].CreatedOnUtc),101)) = 0 then
Sum([Order].OrderSubtotal)
else
case when (DATEDIFF(day,convert(varchar,Min([Order].CreatedOnUtc),101),convert(varchar,Max([Order].CreatedOnUtc),101))/30) = 0 then Sum([Order].OrderSubtotal) else
Sum([Order].OrderSubtotal)/
(DATEDIFF(day,convert(varchar,Min([Order].CreatedOnUtc),101),convert(varchar,Max([Order].CreatedOnUtc),101))/30)
end
end as 'Account Value' from [order] where And Account.ID = #Act_ID
I am trying the code here:
var query = _orderRepository.Table;
query = query.Where(o => o.AccountId == accountId);
In query i am getting my value.
After query statement what should i write??
how do i write for case statement using linq???
#Manoj, may be the below code helps you. This sample C# project may solve the problem you have.
using System;
using System.Collections.Generic;
using System.Linq;
namespace DateDiffIssue
{
class Program
{
static void Main(string[] args)
{
// Preparing data
var data = new Order[] {
new Order { AccountID = 1, CreatedOnUtc = DateTime.Parse("1.01.2017 10:00"), OrderSubtotal = 100 },
new Order { AccountID = 1, CreatedOnUtc = DateTime.Parse("1.01.2017 12:00"), OrderSubtotal = 150 },
new Order { AccountID = 1, CreatedOnUtc = DateTime.Parse("1.01.2017 14:00"), OrderSubtotal = 150 }
};
// Selection
var selected = (from item in data
let accountData = data.Where(w => w.AccountID == 1)
let minDate = accountData.Min(m => m.CreatedOnUtc).Date
let maxDate = accountData.Where(w => w.AccountID == 1).Max(m => m.CreatedOnUtc).Date
let isSameDate = minDate == maxDate
let basedOn30Days = (maxDate - minDate).TotalDays / 30
let isInside30Days = (int)basedOn30Days == 0
let accountDataSum = accountData.Sum(s => s.OrderSubtotal)
select new
{
AccountValue = isSameDate ? accountDataSum :
isInside30Days ? accountDataSum :
accountDataSum / basedOn30Days
}).Distinct();
// Print each order
selected.ToList().ForEach(Console.WriteLine);
// Wait for key
Console.WriteLine("Please press key");
Console.ReadKey();
}
}
internal class Order
{
public int AccountID { get; set; }
public DateTime CreatedOnUtc { get; set; }
public int OrderSubtotal { get; set; }
}
}

RavenDB: How do I fix this Map Reduce code? I'm getting NULL values where I'm expecting Results

I have the following code:
public class WorkOrderByUserId : AbstractMultiMapIndexCreationTask<WorkOrderByUserId.Result>
{
public WorkOrderByUserId()
{
this.AddMap<WorkOrder>(items
=> from item in items
select new Result
{
OwnerId = item.OwnerId,
WorkOrder = new WorkOrderLookupDto
{
Id = item.Id,
Name = item.EventName
},
WorkOrders = null
});
this.AddMap<Invoice>(items
=> from item in items
select new Result
{
OwnerId = item.WorkOrder.OwnerId,
WorkOrder = new WorkOrderLookupDto
{
Id = item.WorkOrder.Id,
Name = item.WorkOrder.EventName
},
WorkOrders = null
});
this.Reduce = results => from result in results
group result by result.OwnerId
into g
select new Result
{
OwnerId = g.Key,
WorkOrders = g.Select(x => x.WorkOrder),
WorkOrder = null
};
this.Indexes.Add(x => x.OwnerId, FieldIndexing.Default);
}
public class Result
{
public string OwnerId { get; set; }
public IEnumerable<WorkOrderLookupDto> WorkOrders { get; set; }
public WorkOrderLookupDto WorkOrder { get; set; }
}
}
It gets me very close to where I want to be, however I seem to be missing something and I'm losing information and I'm not sure why.
Using the Map/Reduce Visualizer I notice the MAP is displaying the Results (i.e. WorkOrders is populated, and WorkOrder is null)
As this point I was expecting to have a bunch of items with NULL WorkOrders and a valid WorkOrder, which I expected to reduce down into the WorkOrders collection.
When I look at the final reduce in the visualizer, I notice my WorkOrder is NULL and my WorkOrders are missing entirely.
And when I look at the FINAL result of the Index I see what I'm looking for, just without the actual data I'm looking for.
What do I need to change to get my final WorkOrders to NOT be NULL?
I was able to get my desired result using the following code:
public class WorkOrderByUserId : AbstractMultiMapIndexCreationTask<WorkOrderByUserId.Result>
{
public WorkOrderByUserId()
{
this.AddMap<WorkOrder>(items
=> from item in items
select new Result
{
OwnerId = item.OwnerId,
WorkOrders = new[]
{
new WorkOrderLookupDto
{
Id = item.Id,
Name = item.EventName
}
}
});
this.AddMap<Invoice>(items
=> from item in items
select new Result
{
OwnerId = item.WorkOrder.OwnerId,
WorkOrders = new[]
{
new WorkOrderLookupDto
{
Id = item.WorkOrder.Id,
Name = item.WorkOrder.EventName
}
}
});
this.Reduce = results => from result in results
group result by result.OwnerId
into g
select new Result
{
OwnerId = g.Key,
WorkOrders = g.SelectMany(x => x.WorkOrders)
};
this.Indexes.Add(x => x.OwnerId, FieldIndexing.Default);
}
public class Result
{
public string OwnerId { get; set; }
public IEnumerable<WorkOrderLookupDto> WorkOrders { get; set; }
}
}

Convert SQL sentence to LINQ

I need to create a LINQ sentence that does the same as this SQL sentence but I can't solve it...
SELECT l.Id, l.Url, t.Name, t.LanguageCode
FROM link l
LEFT OUTER JOIN linktr t ON t.Id = (SELECT tt.Id FROM linktr tt WHERE tt.LinkId = l.Id AND (tt.LanguageCode = 'en-EN' OR tt.LanguageCode = 'es-ES') ORDER BY (tt.LanguageCode = 'en-EN') DESC, tt.LanguageCode LIMIT 1)
ORDER BY l.OrderPos
Table Link
Id, Url
Table LinkTr
Id, LinkId, Name, LanguageCode
The table link contains the Url of the link while the LinkTr contains the name and it can cointain multiple languages
I want to select all the links we have in the links database and for each link I want to show JUST ONE language, the one that corresponds to the current language if exists, but if it doesn't exist I have to show the one that corresponds to the default language. If no one of them exist it wouldn't show that record.
For this example the default language is es-ES and the current one is en-EN.
How can I do this using LINQ?
Thanks in advance
EDIT
If I use this LINQ expression it works only if I comment the ORDER line, but without the ORDER line (.OrderBy(p3 => p3.LanguageCode == currentLanguage)) it takes the first record in the db by Id, but not the current language first.
var queryString = from i in _dbContext.Links
let p = _dbContext.LinksTrs.Where(p2 => i.Id == p2.LinkId && (p2.LanguageCode == currentLanguage || p2.LanguageCode == defaultLanguage))
.OrderBy(p3 => p3.LanguageCode == currentLanguage)
.FirstOrDefault()
orderby i.OrderPos
select new LinksWebListModel
{
Id = i.Id,
Name = (p == null) ? "" : p.Name,
Url = i.Url,
Summary = (p == null) ? "" : p.Summary,
};
EDIT 2
I'm suing EF6 and my entities, which I can't change, are these:
public class Link : EntityBase
{
public int Id { get; set; }
public int OrderPos { get; set; }
public string Url { get; set; }
public virtual IEnumerable<LinkTr> Translations { get; set; }
}
public class LinkTr
{
public int Id { get; set; }
public string Name { get; set; }
public string LanguageCode { get; set; }
public int LinkId { get; set; }
public virtual Link Link { get; set; }
}
EDIT 3
it would be something like this...
var queryString = (from entity in _dbContext.Links
let translation = _dbContext.LinksTrs
.Where(p2 => p2.LinkId == entity.Id)
.Where(p3 => p3.LanguageCode == currentLanguage || p3.LanguageCode == defaultLanguage)
.OrderBy(p4 => p4.LanguageCode)
.FirstOrDefault()
orderby entity.OrderPos descending
select new LinksWebListModel()
{
Id = entity.Id,
Name = translation.Name,
Url = entity.Url,
Summary = translation.Summary,
});
buit the problems here are 2:
- I need to return the record (Links) only if there is a row in the sub query (LinksTrs)
- Also I'd need to order the subquery by "currentLanguage" first and then "defaultLanguage" and then the rest. If I add this to the sub query I get an error:
.OrderBy(p4 => p4.LanguageCode == currentLanguage)
.ThenBy(p5 => p5.LanguageCode == defaultLanguage)
.ThenBy(p6 => p6.LanguageCode)
Do you have an idea on how to order by certain values, for example if I have these languages "es-ES", "en-EN", "it-IT", "fr-FR" for example to get first "it-IT", then "es-ES" and then order by name...

get list of decision for a specific meetingtitle using linq asp.net

I have a database table. What I want is to get data using group by clause as I have used in below code.
Note that Decision is another table. now I want that all the decisions related to a specific Meeting Title should be shown in list.like
meetingtitle1=decision1,decison2,decison3
meetingtitle2=decision1,decison2
but below code returns only one decisiontitle.
public List<NewMeetings> GetAllMeetings()
{
var xyz = (from m in DB.MeetingAgenda
//join mp in Meeting on m.MeetingId equals mp.MeetingId
//where m.MeetingId == 2
group m by new { m.Meeting.MeetingTitle } into grp
select new NewMeetings
{
// meetingid = grp.Key.MeetingId,
meetingtitle = grp.Key.MeetingTitle,
decision = grp.Select(x => x.Decision.DecisionTitle).FirstOrDefault(),
total = grp.Count()
}).ToList();
List<NewMeetings> list = xyz.ToList();
return list;
}
public class NewMeetings
{
public int meetingid;
public string meetingtitle;
public string decision;
public int total;
}
Can somebody please tell me how to return a list of decisions to a specific Meetingtitle?
You are doing a FirstOrDefault on the list of decisions which obviously means you are only getting a single value. Instead you can join them all together into one longer string (separated by commas as you indicated in the question) by changing this line:
decision = grp.Select(x => x.Decision.DecisionTitle).FirstOrDefault(),
To this:
decision = string.Join(",", grp.Select(x => x.Decision.DecisionTitle)),
However, as the string.Join is not recognised by Linq to Entities, you need to do the string.Join after the data has been retrieved (i.e. after the ToList):
var xyz = (from m in DB.MeetingAgenda
group m by new { m.Meeting.MeetingTitle } into grp
select new
{
meetingtitle = grp.Key.MeetingTitle,
decisions = grp.Select(x => x.Decision.DecisionTitle),
total = grp.Count()
})
.ToList()
.Select(m => new NewMeetings
{
meetingtitle = m.meetingtitle,
decision = string.Join(",", m.decisions),
total = m.total
});