Hi I have two entity models that has data in tables as:
Table Group
id name
1 NW
2 SW
3 NE
Second Table is
Location
id groupId count
1 1 34
2 2 5
3 2 90
4 1 33
5 1 23
I want to write a linq query or using context in EF so that i can group by each groupId so that result is
groupdId 1
{count 34, 33, 23}
groupId 2
{count 90,5}
I have tried following
from e in DbContext.Set<Group>()
join a in DbContext.Set<locatin>() on e.Id equals a.groupId
Select new Test
{
groupId= e.groupdId
tables = new List<tbl>()
{
count= a.count;
}
}
public class Test
{
public int groupId {get; set;}
public IEnumerable<gbl> Tables {get; set;}
}
public class tbl
{
public int count {get; set;}
}
In writing the query when I get to count=a.count, I get intellisense error can not resolve. Please let me know how to correct my query so that I get heading of groupId then another array with count numbers only. Thanks.
Following will work in this case:
var result =
groups.Join(locations,g=>g.id,l=>l.groupId,(g,l)=>new {l})
.GroupBy(x =>x.l.groupId,x=>x.l.count)
.Select(y=>new Test
{
groupId= y.Key,
tables = y.Select(n => new tbl{count = n})
});
Following are the steps:
Join two tables groups and locations using the id and groupid
GroupBy the result and project the count
Select and result should be IEnumerable<Test>
Following is my complete code, that I have used to create the solution (using LinqPad):
void Main()
{
var groups = Group.CreateList();
var locations = Location.CreateList();
var result =
groups.Join(locations,g=>g.id,l=>l.groupId,(g,l)=>new {l})
.GroupBy(x =>x.l.groupId,x=>x.l.count)
.Select(y=>new Test
{
groupId= y.Key,
tables = y.Select(n => new tbl{count = n})
});
result.Dump();
}
public class Group
{
public int id;
public string name;
public static List<Group> CreateList()
{
return new List<Group>
{
new Group
{
id = 1,
name = "NW"
},
new Group
{
id = 2,
name = "SW"
},
new Group
{
id = 3,
name = "NE"
}
};
}
}
public class Location
{
public int id;
public int groupId;
public int count;
public static List<Location> CreateList()
{
return new List<Location>
{
new Location
{
id = 1,
groupId = 1,
count = 34
},
new Location
{
id = 2,
groupId = 2,
count = 5
},
new Location
{
id = 3,
groupId = 2,
count = 90
},
new Location
{
id = 4,
groupId = 1,
count = 33
},
new Location
{
id = 5,
groupId = 1,
count = 23
}
};
}
}
public class Test
{
public int groupId {get; set;}
public IEnumerable<tbl> tables {get; set;}
}
public class tbl
{
public int count {get; set;}
}
Related
I have an object:
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public int GroupID { get; set; }
}
I return a list that may look like the following:
List<Customer> CustomerList = new List<Customer>();
CustomerList.Add( new Customer { ID = 1, Name = "One", GroupID = 1 } );
CustomerList.Add( new Customer { ID = 2, Name = "Two", GroupID = 1 } );
CustomerList.Add( new Customer { ID = 3, Name = "Three", GroupID = 2 } );
CustomerList.Add( new Customer { ID = 4, Name = "Four", GroupID = 1 } );
CustomerList.Add( new Customer { ID = 5, Name = "Five", GroupID = 3 } );
CustomerList.Add( new Customer { ID = 6, Name = "Six", GroupID = 3 } );
I want to return a linq query which will look like
CustomerList
GroupID =1
UserID = 1, UserName = "UserOne", GroupID = 1
UserID = 2, UserName = "UserTwo", GroupID = 1
UserID = 4, UserName = "UserFour", GroupID = 1
GroupID =2
UserID = 3, UserName = "UserThree", GroupID = 2
GroupID =3
UserID = 5, UserName = "UserFive", GroupID = 3
UserID = 6, UserName = "UserSix",
I tried from
Using Linq to group a list of objects into a new grouped list of list of objects
code
var groupedCustomerList = CustomerList
.GroupBy(u => u.GroupID)
.Select(grp => grp.ToList())
.ToList();
works but does not give the desired output.
var groupedCustomerList = CustomerList.GroupBy(u => u.GroupID)
.Select(grp =>new { GroupID =grp.Key, CustomerList = grp.ToList()})
.ToList();
var groupedCustomerList = CustomerList
.GroupBy(u => u.GroupID, u=>{
u.Name = "User" + u.Name;
return u;
}, (key,g)=>g.ToList())
.ToList();
If you don't want to change the original data, you should add some method (kind of clone and modify) to your class like this:
public class Customer {
public int ID { get; set; }
public string Name { get; set; }
public int GroupID { get; set; }
public Customer CloneWithNamePrepend(string prepend){
return new Customer(){
ID = this.ID,
Name = prepend + this.Name,
GroupID = this.GroupID
};
}
}
//Then
var groupedCustomerList = CustomerList
.GroupBy(u => u.GroupID, u=>u.CloneWithNamePrepend("User"), (key,g)=>g.ToList())
.ToList();
I think you may want to display the Customer differently without modifying the original data. If so you should design your class Customer differently, like this:
public class Customer {
public int ID { get; set; }
public string Name { get; set; }
public int GroupID { get; set; }
public string Prefix {get;set;}
public string FullName {
get { return Prefix + Name;}
}
}
//then to display the fullname, just get the customer.FullName;
//You can also try adding some override of ToString() to your class
var groupedCustomerList = CustomerList
.GroupBy(u => {u.Prefix="User", return u.GroupID;} , (key,g)=>g.ToList())
.ToList();
is this what you want?
var grouped = CustomerList.GroupBy(m => m.GroupID).Select((n) => new { GroupId = n.Key, Items = n.ToList() });
var result = from cx in CustomerList
group cx by cx.GroupID into cxGroup
orderby cxGroup.Key
select cxGroup;
foreach (var cxGroup in result) {
Console.WriteLine(String.Format("GroupID = {0}", cxGroup.Key));
foreach (var cx in cxGroup) {
Console.WriteLine(String.Format("\tUserID = {0}, UserName = {1}, GroupID = {2}",
new object[] { cx.ID, cx.Name, cx.GroupID }));
}
}
The desired result can be obtained using IGrouping, which represents a collection of objects that have a common key in this case a GroupID
var newCustomerList = CustomerList.GroupBy(u => u.GroupID)
.Select(group => new { GroupID = group.Key, Customers = group.ToList() })
.ToList();
I need to use groupby in my code to show ActionId and group based on the controllerId field.
The problem is, I except I can show ActionId with a select like this :
var group = conList.GroupBy(x => x.ControllerId).Select(x=>x.ActionId).ToList();
But when I use the select it just shows me Key and Count.
this my code:
var group = conList.GroupBy(x => x.ControllerId).Select(x=>x.Key).ToList(););
How would I be able to solve this problem?
Based on you question I did this:
Let's say that you have the following class:
public class Controller
{
public int ControllerId { get; set; }
public int ActionId { get; set; }
}
And the following data:
var list = new List<Controller>()
{
new Controller() { ControllerId = 1, ActionId = 1 },
new Controller() { ControllerId = 1, ActionId = 2 },
new Controller() { ControllerId = 1, ActionId = 3 },
new Controller() { ControllerId = 2, ActionId = 4 },
new Controller() { ControllerId = 2, ActionId = 5 },
new Controller() { ControllerId = 2, ActionId = 6 }
};
What this command says is. Group my object of type Controller by ControllerId (the Key) and for each grouped item (g) I will have a list of type Controller.
var groupedList = list.GroupBy(x => x.ControllerId).Select(g => g);
foreach(var g in groupedList)
{
//g --> is your grouped object a list of type Controller by unique ControllerId.
//g.Key --> is the value of each unique ControllerId.
Console.WriteLine("Group: " + g.Key + " Actions: " + string.Join(";", g.Select(actions => actions.ActionId)));
}
Expected result
Group: 1 Actions: 1;2;3
Group: 2 Actions: 4;5;6
You can test the code above here.
I hope that explanation can help you out with your problem. Good luck!
Here you can find some samples and more explanation about GroupBy here.
I want sum all item prices in all rows in the database table that have the same item id. I mean the result should be one number and put it on textbox automatically when I choose a specific item id from dropdownlist
How can I do it in linq?
Is this achieve what I want or should use Group by .
Tell me what the correct answer:
public double oIlstGetVouchersDetailjh(int nvoucherID)
{
vouchers ovouchers = new vouchers();
double sum = (from Entity in ovouchers.INV_InventoryItems
where Entity.ItemID == nvoucherID
select Entity.ItemPrice).Sum();
return sum;
}
I think you need a new table in the database which contains the ID and the Total value. Your current solution only gets 1 ID. Using Group By will create totals for all id.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
vouchers ovouchers = new vouchers();
ovouchers.INV_InventoryItems = new List<inventory>(){
new inventory{
ItemID = 123, ItemPrice = 1
},
new inventory{
ItemID = 123, ItemPrice = 2
},
new inventory{
ItemID = 123, ItemPrice = 3
},
new inventory{
ItemID = 124, ItemPrice = 1
},
new inventory{
ItemID = 124, ItemPrice = 1
},
};
var inventoryByID = ovouchers.INV_InventoryItems.AsEnumerable()
.GroupBy(x => x.ItemID, y => y.ItemPrice)
.Select(x => new { ID = x.Key, total = x.Sum() });
string boxID = "123";
double itemID = inventoryByID.Where(x => x.ID == int.Parse(boxID)).Select(y => y.total).FirstOrDefault();
}
}
public class vouchers
{
public List<inventory> INV_InventoryItems { get; set; }
}
public class inventory
{
public int ItemID { get; set; }
public double ItemPrice { get; set; }
}
}
Consider these two tables:
ClassID Name
1 C1
2 C2
ClassID List<CourseSession>
1 [Object that has value "A"], [Object that has value "B"]
2 [Object that has value "B"], [Object that has value "C"]
When I join these two tables in Linq, I get:
ID Name List
1 C1 [A, B]
2 C2 [A, B]
Wheras I need to expand them:
ID Name List
1 C1 A
1 C1 B
2 C2 A
2 C2 B
Linq code:
var classes = from row in t.AsEnumerable()
select new
{
ClassID = row.Field<Guid>("ClassID"),
ClassName = row.Field<string>("Name"),
};
var classCourses = from row in classes.AsEnumerable()
select new
{
ID = row.ID,
CourseSessionList = GetAllCoursesByID(row.ID).AsEnumerable()
};
//Attempt to join
var expandedClassCourse = from classRow in classes
join ccRow in classCourses
on classRow.ID equals ccRow.ID
into filteredExpandedClasses
select filteredExpandedClasses;
I'm not sure how to achieve this. Any ideas?
Something like (not sure what your model looks like):
context.CouseSessions.Where(cs => /* condition goes here */)
.Select(cs =>
new
{
Name = cs.Name,
Class = cs.Class.Name
});
or
context.Classes.Where(c => /* condition goes here */)
.SelectMany(c => c.Courses)
.Select(cs =>
new
{
Name = cs.Name,
Class = cs.Class.Name
});
I created two models based on assumption. I hope this helps.
class Info
{
public int Id { get; set; }
public string Name { get; set; }
public List<string> List { get; set; }
}
class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public string s { get; set; }
}
static void Main(string[] args)
{
var infos = new List<Info> { new Info { Id = 1, Name = "c1", List = new List<string> { "A", "B" } }, new Info { Id = 2, Name = "c2", List = new List<string> { "A", "B" } } };
var myClasses = new List<MyClass>();
foreach (var info in infos)
{
myClasses.AddRange(info.List.Select(a => new MyClass { Id = info.Id, Name = info.Name, s = a }));
}
}
(from c in classList
join s in sessionList on c.ClassID equals s.ClassID
select new
{
ID = c.ClassID,
Name = c.Name,
SessionList = s.SessionList
})
.SelectMany(e => e.SessionList.Select(s => new
{
ID = e.ClassID,
Name = e.Name,
Session = s
}))
I'm trying to combine 3 lists of objects. I have a person list, address list and an addressRelation list.
I want to combine these lists into a new list ordered by person.id, use it as a datasource for a listview, and then be able to access the properties in the aspx page.
Is this possible?
Roughly
using System.Linq;
class Person
{
public int Id;
public string Name;
}
class Address
{
public int Id;
public string Street;
}
class PersonAddress
{
public int PersonId, AddressId;
}
public class Program
{
public static void Main(string[] args)
{
var personList = new []
{
new Person { Id = 1, Name = "Pete" },
new Person { Id = 2, Name = "Mary" },
new Person { Id = 3, Name = "Joe" }
};
var addressList = new []
{
new Address { Id = 100, Street = "Home Lane" },
new Address { Id = 101, Street = "Church Way" },
new Address { Id = 102, Street = "Sandy Blvd" }
};
var relations = new []
{
new PersonAddress { PersonId = 1, AddressId = 101 },
new PersonAddress { PersonId = 3, AddressId = 101 },
new PersonAddress { PersonId = 2, AddressId = 102 },
new PersonAddress { PersonId = 2, AddressId = 100 }
};
var joined =
from par in relations
join p in personList
on par.PersonId equals p.Id
join a in addressList
on par.AddressId equals a.Id
select new { Person = p, Address = a };
foreach (var record in joined)
System.Console.WriteLine("{0} lives on {1}",
record.Person.Name,
record.Address.Street);
}
}
Outputs:
Pete lives on Church Way
Mary lives on Sandy Blvd
Mary lives on Home Lane
Joe lives on Church Way