var query = _sqlDbContext.RequestTemplates
.Select(rt => new TemplateViewModel
{
templateName = rt.TemplateName,
requests = _sqlDbContext.RequestTemplateItems
.Where(ti => ti.RequestTemplateID == rt.RequestTemplateID)
.Select(ti => new RequestViewModel
{
category = new CategoryViewModel
{
categoryId = ti.RequestCategoryID,
categoryName = ti.RequestCategory.RequestCategoryName
},
items = new List<ItemViewModel> { new ItemViewModel
{
itemName = ti.ItemName,
dueDate = ti.DueDate,
notes = ti.Notes
}}
})
.ToList()
});
As per above LINQ query I am getting below result :-
"requests":[
{
"category":{
"categoryId":2,
"categoryName":"2"
},
"items":[
{
"itemName":"2 Item 1",
"dueDate":"",
"notes":"Item 1 Note"
}
]
},
{
"category":{
"categoryId":2,
"categoryName":"2"
},
"items":[
{
"itemName":"2 Item 2",
"dueDate":"",
"notes":""
}
]
}
for same category id , items are returning two time . i was unable to find where i need to add grouping to get below output
"requests":[
{
"category":{
"categoryId":2,
"categoryName":"2"
},
"items":[
{
"itemName":"2 Item 1",
"dueDate":"",
"notes":"Item 1 Note"
},
{
"itemName":"2 Item 2",
"dueDate":"",
"notes":"Item 1 Note"
}
]
}
Model information as below
RequestTemplates having list of RequestTemplateItem with primary key RequestTemplateID.
RequestTemplateItem having object of RequestTemplate and RequestCategory with FK_RequestTemplateID and FK_RequestCategoryID.
Haven't tested but something like this should work:
var query = _sqlDbContext.RequestTemplates
.Select(rt => new TemplateViewModel
{
templateName = rt.TemplateName,
requests = _sqlDbContext.RequestTemplateItems
.Where(ti => ti.RequestTemplateID == rt.RequestTemplateID)
.GroupBy(ti => ti.RequestCategoryId)
.Select(group => new RequestViewModel
{
category = new CategoryViewModel
{
categoryId = group.Key,
categoryName = group.First().RequestCategoryName
},
items = group.select(ti => new ItemViewModel
{
itemName = ti.ItemName,
dueDate = ti.DueDate,
notes = ti.Notes
}
})
.ToList()
});
Related
I believe the title doesn't help much, I'll try to explain better here... and hopefully you can help me.
I have this class
public class ItemValue
{
public string SetId {get; set;}
public string ItemId {get; set;}
public string Value {get; set;}
}
And I have a collection of objects of this class like this one
IEnumerable<ItemValue> = new List<ItemValue>()
{
new ItemValue
{
SetId = "S1",
ItemId = "I1",
Value = "S1I1V",
},
new ItemValue
{
SetId = "S1",
ItemId = "I2",
Value = "S1I2V",
},
new ItemValue
{
SetId = "S1",
ItemId = "I3",
Value = "S1I3V",
},
new ItemValue
{
SetId = "S2",
ItemId = "I1",
Value = "S2I1V",
},
new ItemValue
{
SetId = "S2",
ItemId = "I2",
Value = "S2I2V1",
},
new ItemValue
{
SetId = "S2",
ItemId = "I2",
Value = "S2I2V2",
},
new ItemValue
{
SetId = "S2",
ItemId = "V3",
Value = "S2I3V",
}
};
Notice there are 2 instances with SetId="S2" and ItemId="I2" with different values
What I need is to map this collection to something like this using LINQ
var expectedResult = new Lookup<string, IDictionary<string, string>>()
{
["S1"] = new Dictionary<string, string>()
{
{ ["I1"] = "S1I1V" },
{ ["I2"] = "S1I2V" },
{ ["I3"] = "S1I3V" },
},
["S2"] = new Dictionary<string, string>()
{
{ ["I1"] = "S2I1V" },
{ ["I2"] = "S2I2V1" },
{ ["I3"] = "S2I3V" },
},
["S2"] = new Dictionary<string, string>()
{
{ ["I1"] = "S2I1V" },
{ ["I2"] = "S2I2V2" },
{ ["I3"] = "S2I3V" },
}
};
I'm not good at LINQ myself and after some unsuccessful LINQ trials and an ugly solution using a bunch of foreach and ifs, I'm now reaching you to please get some ideas for this.
If you need any additional information, please just let me know
Thank you very much in advance!...
you could do something similar with GroupBy and ToDictionary/ToLookup
var dict = items.GroupBy(i => i.SetId)
.ToDictionary(
group => group.Key,
group => group.ToLookup(i => i.ItemId, i => i.Value));
dict["S2"]["I2"].ToList() // usage example
An alternative would be
var dict2 = items.ToLookup(i => (i.SetId, i.ItemId), i => i.Value);
dict2[("S2", "I2")].ToList() // usage example
I have a question about a LINQ grouping.
I thought that grouping would be a simple matter of using the GroupBy function on the result set and specifying what to group it by. However my items appear to not be grouping together and instead are displaying as if the GroupBy function wasn't there. I want to group by the itemPk, but I'm can't seem to do it. I have tried grouping by both category.ItemFk and Item.Itempk, but no luck. Could someone give me a pointer on this?
var itemIds = items.Select(i => i.ItemId).ToList();
var itemAndCatJoin =
from item in Context.SCS_Items
join category in Context.SCS_ItemCategories
on item.ItemPk equals category.ItemFk
into temp
from category in temp.DefaultIfEmpty()
select new ExportItemTable
{
Category = category,
Item = item
};
return itemAndCatJoin.Where(i => itemIds.Contains(i.Item.ItemPk))
.GroupBy(n => new {n.Item, n.Category})
.Select(i => new ExportableItem
{
ItemPk = i.Key.Item.ItemPk,
Name = i.Key.Item.Name,
Description = i.Key.Item.Description,
Price = i.Key.Item.Price,
Category = i.Key.Category.Category.Category_Name,
GLDepartment = i.Key.Category.GL_Department.Name ?? "",
GLName = i.Key.Category.GL_Name.Name ?? "",
StartDate = i.Key.Item.StartDate,
EndDate = i.Key.Item.EndDate,
FiscalYear = i.Key.Item.SCS_FiscalYear.Name,
School = i.Key.Item.School != null ? i.Key.Item.School.School_Name : i.Key.Item.Board.Board_Name,
Beneficiary = i.Key.Item.SCS_Beneficiary.Name,
Quantity = i.Key.Item.MaxQuantity,
Deleted = i.Key.Item.DeletedFlag,
OptionalStudents = i.Key.Item.SCS_Attachments.Where(a => !a.IsRequired).SelectMany(a => a.SCS_StudentAttachments).Where(s => !s.DeletedFlag).Select(s => s.StudentFk).Distinct().Count(),
RequiredStudents = i.Key.Item.SCS_Attachments.Where(a => a.IsRequired).SelectMany(a => a.SCS_StudentAttachments).Where(s => !s.DeletedFlag).Select(s => s.StudentFk).Distinct().Count(),
IsPublic = i.Key.Item.IsPublic,
AllowRecurring = i.Key.Item.AllowRecurringPayments,
EffectiveCutoff = i.Key.Item.SCS_Attachments.Where(a => !a.DeletedFlag && a.CourseDropCutoff.HasValue).Select(a => a.CourseDropCutoff).OrderBy(a => a).FirstOrDefault(),
CreatedDate = i.Key.Item.CreatedDate
}).OrderBy(i => i.ItemPk).ToList();
}
your groupbyy is indeed doing nothing for you, you need to tell the groupby what to group by....
like
.GroupBy(n => n.Category)
Here is a simple example to your grouping question:
class Program
{
static void Main()
{
var allItems = GetAllItems();
var groups = from item in allItems
group item by item.Category
into newGroup
select newGroup;
foreach (var group in groups)
{
Console.WriteLine($"\nCategory: {group.Key}");
foreach (var item in group)
{
Console.WriteLine($"{item.Name}: {item.Price}");
}
}
Console.ReadLine();
}
static List<Category> GetAllCategories()
{
return new List<Category>()
{
new Category() { Id = 1, Name = "Programming Books" },
new Category() { Id = 2, Name = "Fiction Books" }
};
}
static List<Item> GetAllItems()
{
return new List<Item>()
{
new Item() { Id = 1, Name = "Embedded Linux", Category = 1, Price = 9.9 },
new Item() { Id = 2, Name = "LINQ In Action", Category = 1, Price = 36.19 },
new Item() { Id = 3, Name = "C# 6.0 and the .NET 4.6 Framework", Category = 1, Price = 40.99 },
new Item() { Id = 4, Name = "Thinking in LINQ", Category = 1, Price = 36.99 },
new Item() { Id = 5, Name = "The Book Thief", Category = 2, Price = 7.99 },
new Item() { Id = 6, Name = "All the Light We Cannot See", Category = 2, Price = 16.99 },
new Item() { Id = 7, Name = "The Life We Bury", Category = 2, Price = 8.96 }
};
}
}
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
This example is simple enough for anyone new to LINQ. I am sure you can make some adjustment to make it work for your specific issue. Hope this will help.
I got the requirement to serialize my C# class RoomType like the below
public class RoomType
{
public string name { get; set; }
public string url { get; set; }
public string desc { get; set; }
}
to the below json format like this
"room_types" :
{
"Fenway Room" :
{
"url" : "http://www.partner-site.com/hotel_commonwealth/fenway_room",
"desc" : "One king bed with pillowtop mattress, Frette Italian linens, down bedding, multiple pillows. View of Fenway Park."
},
"Commonwealth Room" :
{
"url" : "http://www.partner-site.com/hotel_commonwealth/commonwealth_room",
"desc" : "One king bed with pillowtop mattress, Frette Italian linens, down bedding, multiple pillows. View of Commonwealth Avenue."
}
}
How to get the "Fenway Room" and "Commonwalth Room" to in this json format?
I tried the suggestion but still can't get how the anonymous fit into what i needed in the ActionResult. Here's my not working code now:
var rooms = new List<HarRoomType>()
{
new HarRoomType()
{
}
};
var anonymous = new
{
type = rooms.ToDictionary(x => x.name, x => new {x.currency, x.discounts})
};
var response = new HotelAvailabilityResponse()
{
api_version = 4,
hotel_ids = new List<int>()
{
1,
2
},
start_date = "2014-02-21",
hotels = new List<HarHotel>()
{
new HarHotel()
{
hotel_id = 1,
room_types = anonymous
},
new HarHotel()
{
hotel_id = 2,
room_types = new List<HarRoomType>()
}
}
};
return Json(response, JsonRequestBehavior.AllowGet);
You need to shape the data as a dictionary:
RoomType[] rooms = ...
var serializeThis = new {
room_types = rooms.ToDictionary(
x => x.name,
x => new { x.url, x.desc }
)
};
JavaScriptSerializer js = new JavaScriptSerializer();
List<RoomType> roomTypes = new List<RoomType>(){
new RoomType{ desc="desc 1", name="Fenway Room", url="blah.com"},
new RoomType{ desc="desc 2", name="Commonowealth Room", url="blah.com"},
};
If you don't care about having the name show up as a property, then:
var json = js.Serialize(roomTypes.ToDictionary(x => x.name));
If you do care about having the name show up and don't want it to:
var json2 = js.Serialize(roomTypes.ToDictionary(x => x.name, x => new { desc = x.desc, url = x.url }));
Use this:
var anonymous= new {
type= rooms.ToDictionary(
x => x.name,
x => new { x.url, x.desc }
)
I have a list of data structures:
public List<Personal> Personals()
{
return new List<Personal>
{
new Personal
{
Id = 0,
Name = "Name 0"
},
new Personal
{
Id = 1,
Name = "Name 1",
ParentId = 0
},
new Personal
{
Id = 2,
Name = "Name 2",
ParentId = 0
},
new Personal
{
Id = 3,
Name = "Name 3",
ParentId = 0
},
new Personal
{
Id = 4,
Name = "Name 4",
ParentId = 1
},
new Personal
{
Id = 5,
Name = "Name 5",
ParentId = 1
},
new Personal
{
Id = 6,
Name = "Name 6",
ParentId = 2
},
new Personal
{
Id = 7,
Name = "Name 7",
ParentId = 2
},
new Personal
{
Id = 8,
Name = "Name 8",
ParentId = 4
},
new Personal
{
Id = 9,
Name = "Name 9",
ParentId = 4
},
};
}
and I want to build a tree:
public List<Tree> Trees()
{
return new List<Tree>
{
new Tree
{
Id = 0,
Name = "Name 0",
List = new List<Tree>
{
new Tree
{
Id = 1,
Name = "Name 1",
List = new List<Tree>
{
new Tree
{
Id = 4,
Name = "Name 4"
},
new Tree
{
Id = 5,
Name = "Name 5"
}
}
}
}
}
};
}
How do you build a tree with LinQ to object? I have to use but it doesn't work exactly, see below:
public List<Tree> GetTree(List<Personal> list)
{
var listFormat = list.Select(x => new Tree
{
Id = x.Id,
Name = x.Name,
ParentId = x.ParentId
}).ToList();
var lookup = listFormat.ToLookup(f => f.ParentId);
foreach (var tree in listFormat)
{
tree.List = lookup[tree.Id].ToList();
}
return listFormat;
}
You should use recursion:
public void SomeMethod() {
// here you get your `list`
var tree = GetTree(list, 0);
}
public List<Tree> GetTree(List<Personal> list, int parent) {
return list.Where(x => x.ParentId == parent).Select(x => new Tree {
Id = x.Id,
Name = x.Name,
List = GetTree(list, x.Id)
}).ToList();
}
Same as above only this code checks for the case that your root node has a ParentID that matches its own ID.
public void SomeMethod()
{
// here you get your `list`
var tree = GetTree(list, 0);
}
public List<Tree> GetTree(List<Personal> list, int parent)
{
return list.Where(x => x.ParentId == parent).Select(x => new Tree
{
Id = x.Id,
Name = x.Name,
List = x.ParentId != x.Id ? GetTree(list, x.Id) : new List<Tree>()
}).ToList();
}
I am using a class to store data and then using controller and a view to show the data on the screen on a Website using MVC3 however I am coming across an error, help would be appreciated.
Class:
public class SampleData : DropCreateDatabaseIfModelChanges<TicketBookingEntities>
{
protected override void Seed(TicketBookingEntities context)
{
var productions = new List<Production>
{
new Production { Name = "Peter Pan" },
new Production { Name = "Mary Poppins" },
new Production { Name = "Pirates of the Carribean" },
new Production { Name = "Joseph" },
new Production { Name = "Billy Elliot" },
};
var directors = new List<Director>
{
new Director { Name = "Jason Brown" },
new Director { Name = "Dan Elish" },
new Director { Name = "Lee Hall" },
new Director { Name = "Billie Armstrong" },
new Director { Name = "Willy Russell" },
};
new List<Performance>
{
new Performance {Title = "Test", Genre = productions.Single(g => g.Name == "Peter Pan"), Director = directors.Single(a => a.Name == "Jason Brown"), Price = 9.99M, AlbumArtUrl = "/Content/Images/placeholder.gif" },
}.ForEach(a => context.Performances.Add(a));
}
}
}
Controller:
public ActionResult Browse(string genre)
{
var productionModel = storeDB.Productions.Include("Performances")
.Single(g => g.Name == genre);
return View(productionModel);
}
View:
#model Assignment2.Models.Production
#{
ViewBag.Title = "Browse";
}
<h2>Browsing Production: #Model.Name</h2>
<ul>
#foreach (var performance in Model.Performances)
{
<li>
#performance.Title
</li>
}
</ul>
The Error:
Sequence contains no elements
You don't have a list, you only have one element. Take out the foreach loop.
Managed to solve the issue, changed genre to production on the controller