LINQ groupby to List<List<object>> - c#

I have an ASP.NET MVC view where I'm using LINQ to split a model into multiple lists of an object.
The code below works in that I get the correct list of objects in var data but I cannot then cast it to my object to access the properties. I get error
Unable to cast object of type
'Grouping[<>f__AnonymousType3'2[System.DateTime,System.String],MVCProj.Models.tblData2017]'
to type 'MVCProj.Models.tblData2017
Index.cshtml View:
#model IEnumerable<MVCProj.Models.tblData2017>
#{
ViewBag.Title = "Index";
}
<h2>Title</h2>
#{
var data = Model.Where(x => x.Start.Date == DateTime.UtcNow.Date)
.GroupBy(x => new { x.Start, x.Field2 }).ToList();
for (int i = 0; i < data.Count; i++)
{
var rowItem = (List<tblCards2017>)data[i]; //<-Error on this line
string header1 = $"{rowItem.Start.ToString("HH:mm")} {rowItem.Field2}";
}
}
How can I do either of the following
i) Successfully cast var rowItem = (List<tblCards2017>)data[i];
or
ii) Use linq to get the correct object type List<List<tblCards2017> data = Model.Where..... instead of the current type var data = System.Collections.Generic.List<System.Linq.IGrouping<<>f__AnonymousType2<System.DateTime, string>, MVCProj.Models.tblData2017>>

I think you are looking this:
var data = Model.Where(x => x.Start.Date == DateTime.UtcNow.Date)
.GroupBy(x => new { x.Start, x.Field2 })
.Select(g=>g.ToList()).ToList();
Add a Select call to get a list per each group

Related

Using GroupBy in .NET Core

I need to grouping in the result of my query. The main problem is that when I use GroupBy, the return type of GroupBy statement is IGrouping that is different from the return type of my method which is List<MyViewModel>. So theses two types does not match. Now the first option is to change the return type of my method. In this case how I can access to the properties of my ViewModel in view layer(HTML part of Razor Page)?
Is there any option to using GroupBy without changing the return type of my method?
public List<MultimediaViewModel> Search(MultimediaSearchModel searchModel)
{
var query = _hContext.Multimedias.Include(x => x.Ceremony)
.Select(g => new MultimediaViewModel
{
Id = g.Id,
Title = g.Title,
CeremonyId = g.CeremonyId,
Ceremony = g.Ceremony.Title,
FileAddress = g.FileAddress,
}).AsEnumerable().GroupBy(g => g.CeremonyId).ToList();
if (!string.IsNullOrWhiteSpace(searchModel.Title))
query = query.Where(g => g.Title.Contains(searchModel.Title)).ToList();
if (searchModel.CeremonyId != 0)
query = query.Where(g => g.Key == searchModel.CeremonyId).ToList();
return query;
}
the above code is not working because of the difference between method return type and Group by return type.
without knowing your business needs completely I can offer 2 ways to get around this
use the GroupBy outside the method, use the Search method to return a list and then use GroupBy to group it
if you only need to return a list of MultimediaViewModel for a specific CeremonyId, you can search the list of IGrouping to get a specific sub list
public List<MultimediaViewModel> Search(MultimediaSearchModel searchModel)
{
var query = _hContext.Multimedias.Include(x => x.Ceremony).Select(g => new MultimediaViewModel
{
Id = g.Id,
Title = g.Title,
CeremonyId = g.CeremonyId,
Ceremony = g.Ceremony.Title,
FileAddress = g.FileAddress
}).GroupBy(g => g.CeremonyId).ToList();
return query.FirstOrDefault(g=>g.Key==searchModel.CeremonyId).ToList();
//you can just use Where to find all of the MultimediaViewModel instead of using GroupBy
EDIT
maybe return the result as a Dictionary
public Dictionary<string, List<MultimediaViewModel>> Search(MultimediaSearchModel searchModel)
{
var query = _hContext.Multimedias.Include(x => x.Ceremony).Select(g => new MultimediaViewModel
{
Id = g.Id,
Title = g.Title,
CeremonyId = g.CeremonyId,
Ceremony = g.Ceremony.Title,
FileAddress = g.FileAddress
}).GroupBy(g => g.CeremonyId).ToList();
return query.ToDictionary(k => k.Key, v => v.ToList());
}

Only primitive types or enumeration types are supported in this context on data filtering

I am getting error saying System.NotSupportedException: 'Unable to create a constant value of type 'ZikFunnelItemUpdate_Console.Models.Item'. Only primitive types or enumeration types are supported in this context.'
Please also check in picture for deleteList, updateList, addList same code working but on deleteImageList since i am using db.ItemGalleries to fetch and find data from database using entityframework i am getting following error. My question do you know any quick fix to solve this issue? Please ask if you have question. Please note: Item and ItemGallery ItemID is linked primary key
Main code:
var EixistingItems = db.Items.Where(x => x.UserStoresID == uStore.UserStoresID).ToList();
var addList = new List<Item>();
var updateList = new List<Item>();
var deleteList = new List<Item>();
var deleteImageList = new List<ItemGallery>();
deleteList = EixistingItems.Where(ei => !MyItemList.Any(ni => ni.EbayID == ei.EbayID)).ToList();
updateList = EixistingItems.Where(ei => MyItemList.Any(ni => ni.EbayID == ei.EbayID)).ToList();
addList = MyItemList.Where(ni => !EixistingItems.Any(ei => ei.EbayID == ni.EbayID)).ToList();
deleteImageList = db.ItemGalleries.Where(ei => deleteList.Any(ni => ni.ItemID == ei.ItemID)).ToList();
You can find list of ItemID from deleteList and check .Contains as below:
deleteListIds = deleteList.Select(ni => ni.ItemID).ToList();
deleteImageList = db.ItemGalleries.Where(ei => deleteListIds.Contains(ei.ItemID)).ToList();
You can use select statement after where statement like
deleteImageList = db.ItemGalleries.Select(x=> new ItemGallery{/*Select Items*/}).Where(ei => deleteList.Any(ni => ni.ItemID == ei.ItemID)).Select(x=> new ItemGallery{/*Select Items*/}).ToList();

ViewBag on ListBox gets empty data

I made a LINQ Statement to fill a ViewBag and display it on my View, however for some reason my ListBox displays empty so i saved the LINQ statement on a txt file to see if it was empty, but it has the correct data, so my question is:
Why my ViewBag is not Displaying on my ListBox in my View?
This is my Linq Filling the ViewBag:
foreach (var item in db.VENTA_PLATILLOS
.Select(v => new { Turno = v.Nombre_Turno, Total = v.Total })
.GroupBy(l => l.Turno)
.AsEnumerable()
.Select(z => new { Turno = z.Key, Total = String.Format("{0:$#,##0.00;($#,##0.00);Zero}", Decimal.Round(z.Sum(l => l.Total), 0)) })
.OrderByDescending(a => a.Turno))
{
listadesumas.Add(string.Format("{{{0}, Total = {1}}}", item.Turno, item.Total));
}
//txt file to see if Linq Statemnt is filled correctly and it is
var json5 = JsonConvert.SerializeObject(listadesumas);
System.IO.File.WriteAllText(#"C:\inetpub\wwwroot\SumasTurno.txt", json5);
//Filling my Viewbag with my LinQ Group By Result
var grupos = new SelectList(listadesumas.ToList());
ViewBag.Group = grupos;
This is my View ListBox:
#{
var group = (SelectList)ViewBag.Group;
}
#Html.ListBox("Group", (IEnumerable<SelectListItem>)ViewBag.Group, new { style = "width: 300px;" })
Try the following in your controller instead...
ViewBag["Group"] = grupos;
...and this in the view...
#Html.ListBox("Group", (IEnumerable<SelectListItem>)ViewBag["Group"], new { style = "width: 300px;" })
I have tried your example as best as I could without knowing the underlying database table. I have not found an issue and found that it does render the option list correctly through a viewbag property containing a select list. So in this example, I stubbed in a string list for the underlying database table. In this example, I am able to populate the option list through the viewbag property containing the resulting a list. I have to wonder if your conclusion that it is not displaying is related to contents of the viewbag property "Group"
My example code:
public ActionResult Index()
{
List<string> listadesumas = new List<string>();
var FakeDbTable = new List<string>() { "a.bc", "a.cde", "b.xyz" };
foreach (var item in FakeDbTable.Select(v=> new { itemname = v })
.GroupBy(l => l.itemname.Substring(0, 1)).AsEnumerable().Select(z =>new { GroupingValue= z.Key, Total=string.Format("count {0}",z.Count())}).OrderByDescending(a=>a.GroupingValue))
{
listadesumas.Add(string.Format(" result item {0}",item));
}
var grupos = new SelectList(listadesumas.ToList());
ViewBag.Group = grupos;
return View();
}
The view code
#{
ViewBag.Title = "Home Page";
var group = (SelectList)ViewBag.Group;
}
<div class="row">
<div class="col-md-12">
#Html.ListBox("Group", (IEnumerable<SelectListItem>)ViewBag.Group, new { style = "max-width: 500px;" })
</div>
</div>
Result shows as this:

Using Pagination getting System.Collections.Generic.List does not contain a definition for error

I have a Project that I need to add Pagination to but I keep getting an error when loading it up. I found this link, http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application, on the MSDN site. I am working through it put this code in my controller:
[HttpGet]
public ActionResult TechOpenTickets(int? page)
{
ViewBag.Title = "Open Tickets Assigned To Me";
var model = FindTechTickets(new Guid(Properties.Settings.Default.ActiveID));
int pageSize = 3;
int pageNumber = (page ?? 1);
return View("TechOpen", model.ToPagedList(pageNumber, pageSize));
}
private IEnumerable<Ticket> FindTechTickets(Guid ticketStatusId)
{
Guid g = Guid.Parse(Session["LoggedUserID"] as string);
return db.Tickets
.Include(t => t.TicketNotes)
.Where(t => t.TechnicianId == g).Where(t => t.TicketStatusId == ticketStatusId)
.OrderBy(t => t.OpenDate)
.ToList();
}
and then in my view, I have this at the top:
#model PagedList.IPagedList<HelpDesk.Model.Ticket>
#using PagedList;
I am receiving the following error when on the 'Return View...' line in my Controller.
'System.Collections.Generic.List<HelpDesk.Model.Ticket>' does not
contain a definition for 'ToPagedList'
What am I missing?

c# lambda expression error...this dictionary requires a model item of type

When I change query I got an error. Could you please help?
public ActionResult Index(int? id)
{
Models.MyProjectEntities entity = new Models.MyProjectEntities();
// NORMAL QUERY, NO PROBLEM
//var Messages = entity.Message.Where(x => x.Active);
// JOINED QUERY, GENERATES ERROR
var Messages = entity.Message.Join(entity.Categories,
m => m.CategoriID,
k => k.CategoriID,
(m, k) => new { Message = m, Categories = k })
.Where(x => x.Message.Active);
return View(Messages);
}
Here is aspx file first line
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MyProject.Models.Message>>" %>
Here is the Error
The model item passed into the dictionary is of type 'System.Data.Objects.ObjectQuery`1[<>f__AnonymousType7`2[MyProject.Models.Message,MyProject.Models.Categories]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MyProject.Models.Message]'.
Your view is declared as taking a set of Messages.
You're trying to pass it a set of anonymous types.
As the error clearly states, it doesn't fit.
Instead, you should create a class to hold the data from the join, then declare the view as taking a set of that class.
(Views cannot easily use anonymously typed models)
Because your joining an your creating an anonymous type, you need to do
var Messages = entity.Message.Join(entity.Categories,
m => m.CategoriID,
k => k.CategoriID,
(m, k) => new { Message = m, Categories = k })
.Where(x => x.Message.Active)
.Select(x => new Message { ... .. .. } );
public ActionResult Index(int? id)
{
Models.MyProjectEntities entity = new Models.MyProjectEntities();
// NORMAL QUERY, NO PROBLEM
//var Messages = entity.Message.Where(x => x.Active);
// JOINED QUERY, GENERATES ERROR
var Messages = entity.Message.Join(entity.Categories,
m => m.CategoriID,
k => k.CategoriID,
(m, k) => new { Message = m, Categories = k })
.Where(x => x.Message.Active)
.Select(x => x.Message);
return View(Messages);
}
or if you need categories as well, you should change views model type
EDIT:
public ActionResult Index(int? id)
{
Models.MyProjectEntities entity = new Models.MyProjectEntities();
// NORMAL QUERY, NO PROBLEM
//var Messages = entity.Message.Where(x => x.Active);
// JOINED QUERY, GENERATES ERROR
var Messages = entity.Message.Join(entity.Categories,
m => m.CategoriID,
k => k.CategoriID,
(m, k) => new MessageWithCategories { Message = m, Categories = k })
.Where(x => x.Message.Active);
return View(Messages);
}
and model type should be MessageWithCategories (this class has to be created)

Categories

Resources