I have a linq query which is working fine.How can i use group by in this query.I need to group by username and itemid and i should get sum(Amount)(All are in table called Carts)
FoodContext db = new FoodContext();
List<CartListing> fd = (from e in db.FoodItems
join o in db.Carts on e.itemid equals o.itemid
where e.itemid == o.itemid
select new CartListing
{
Itemname =e.itemname,
Amount =o.amount,
Price=(float)(e.price*o.amount),
}).ToList();
CartModel vm = new CartModel { CartListings = fd };
I can't see username anywhere in your code example, but to group by Itemname and sum Amount, you would something like:
var grouped = fd.GroupBy(
cl => cl.Itemname,
(key, group) => new CartListing
{
Itemname = key,
Amount = group.Sum(cl => cl.Amount),
Price = group.Sum(cl => cl.Price)
});
To also group by username, just generate a text key containing both values, for instance delimited by a character you know will be contained in neither.
Use:
var grouped = fd.GroupBy((a => new { a.itemid,a.name }) into grp
select new MyClass
{
MyProperty1=grp.key.itemid,
MyProperty2 =grp.Sum(x=>x.whatever)
}
Public MyClass
{
public string MyProperty1 {get;set;}
public int MyProperty2 {get;set;}
}
This way it won't be anonymous
Related
Could I please get some help with querying from a JSON file? Populating a datagrid view works just fine but what I am trying to do now is filter the data using LINQ which I'm really struggling with.
This works just fine, populating the datagridview with all of my jsonfile data
//dataGridView1.DataSource = (from p in movie2
// select p).ToArray();
Below is what I have been playing around with. When I group by employee ID into g, I can not longer use my p references to fields.
using (StreamReader file = File.OpenText(#"C:\temp\GRMReportingJSONfiles\Assigned_FTE\" + myFile))
{
JsonSerializer serializer = new JsonSerializer();
IEnumerable<AssgnData> movie2 = (IEnumerable<AssgnData>)serializer.Deserialize(file, typeof(IEnumerable<AssgnData>));
dataGridView1.DataSource = (from p in movie2
group p by p.EMPLID[0] into g
select new {
EMPLID = p.EMPLID,
(decimal?)decimal.Parse(p.MNTH1) ?? 0).Sum(),
};
);
//dataGridView1.DataSource = (from p in movie2
// select Int32.Parse(p.MNTH1).Sum();
dataGridView1.DataSource = (from p in movie2
group p by p.EMPLID[0] into g
select (decimal?)decimal.Parse(p.MNTH1) ?? 0).Sum(); //dataGridView1.DataSource = (from p in movie2
// select p).ToArray();
//where p.Resource_BU == "7000776"
//chart1.DataBindCrossTable(movie2, "MNTH1", "1", "PROJECT_ID", "Label = FTE");
//chart1.Refresh();
}
Here is part of the array layout, removed other fields for now as I was just trying to focus on these two, dataset has 100k rows and 50 columns
public class AssgnData
{
public string EMPLID { get; set; }
public string MNTH1 { get; set; }
}
In my opinion, using Fluent Syntax usually makes it a bit easier to understand what is going wrong here.
As soon as you group your data you are no longer working on the individual objects, but on a 'group', which is the key and an enumerable of objects.
Getting the sum per employee should then be grouping by the full employee id and then parsing the MNTH1 fields of your objects and summing them.
dataGridView1.DataSource = movie2
.GroupBy(p => p.EMPLID) // create a group of data per employee
.Select(g => new
{
EMPLID = g.Key, // the employee id is the group key
Sum = g.Sum(data => decimal.Parse(data.MNTH1)) // parse and sum
})
.ToArray();
Edit: you are right, you need the ToArray to evaluate the query. I just verified on my computer and it works.
Try following :
class Program
{
static void Main(string[] args)
{
IEnumerable<AssgnData> movie2 = null;
dataGridView1.DataSource = movie2.GroupBy(x => new {id = x.EMPLID, month = x.MNTH1})
.Select(x => new {
EMPLYID = x.Key.id,
MONTH = x.Key.month,
SUM = x.Sum(y => y.value)
});
}
}
public class AssgnData
{
public string EMPLID { get; set; }
public string MNTH1 { get; set; }
public int value { get;set;}
}
Sort in LINQ
I have 2 database CustomerEntities and BillEntities
I want to get CustomerName from CustomerEntities and sort it but it have no data and I want .ToList() just once time because it slow if used many .ToList()
using (var db1 = new CustomerEntities())
{ using (var db2 = new BillEntities())
{
var CustomerData = db1.Customer.Select(s=> new{s.CustomerCode,s.CustomerName}).ToList();
var BillData = (from t1 in db2.Bill
select new {
BillCode = t1.Billcode,
CustomerCode = t1.Customer,
CustomerName = ""; //have no data
});
}
if(sorting.status==true)
{
BillData= BillData.OrderBy(o=>o.CustomerName); //can't sort because CustomerName have no data
}
var data = BillData .Skip(sorting.start).Take(sorting.length).ToList(); // I want .ToList() just once time because it slow if used many .ToList()
foreach (var b in data)
{
var Customer = CustomerData.FirstOrDefault(f => f.CustomerCode==b.CustomerCode );
if(CustomerName>!=null)
{
r.CustomerName = Customer.CustomerName; //loop add data CustomerName
}
}
}
I have no idea to do it. Help me please
I'm not sure if I understand your code but what about this:
var BillData = (from t1 in db2.Bill
select new {
BillCode = t1.Billcode,
CustomerCode = t1.Customer,
CustomerName = db1.Customer.FirstOrDefault(c => c.CustormerCode == t1.Customer)?.CustomerName
});
Then you have objects in BillData that holds the CustomerName and you can order by that:
BillData.OrderBy(bd => bd.CustomerName);
If you just want to get CustomerName from your customer Db and sort it, this is what i would have used. I used orderByDescending but you can use OrderBy aswell.
public List<Customer> getLogsByCustomerName(string customername)
{
using (var dbentites = new CustomerEntities())
{
var result = (from res in dbentites.Customer.OrderByDescending(_ => _.CustomerName)
where res.CustomerName == customername
select res).ToList();
return result.ToList();
}
}
I have a table like below: I need to display it as without duplicates. So I need to groupby customer alone. c1 has both 'Name'
Id Name customer
1 XXXX c1
2 YYYY c1
I need to get the values on c1 : xxx ,yyy. But its getting c1: xxx and c1: yyy.
My code is:
public List<data> GetComponentStatus()
{
List<data> d= null;
using(var entity=new FM())
{
d = entity.getdata()
.Select(
a => new data
{
Customer = a.id,
Name = a.name,
})
.GroupBy(a=>a.Customer).Select(a=>a.FirstOrDefault()).ToList();
}
return d;
}
From this, I am getting the first record or last record when using LastorDefault().
I want to get both 'Name' on single Customer C1.
If I understood correctly you want to group by Customer and get Name as comma seperated. I created sample data of yours and wrote LINQ in query syntax. See the demo output on rextester below.
var data = new[] { new {ID = 1,Name = "XXXX", customer= "C1"},
new {ID = 2,Name = "YYYY", customer= "C1"},
};
var query = from a in data
group a by a.customer into grp
select new {Cutomer= grp.Key ,Name = string.Join(",",grp.Select (g => g.Name)) };
foreach (var e in query)
{
Console.WriteLine("Customer: {0} ,Name: {1}", e.Cutomer,e.Name);
}
Its Demo on rextester
So your code should be like this
public List<data> GetComponentStatus()
{
using(var entity=new FM())
{
var d = from a in entity.getdata()
group a by a.customer into grp
select new data {Cutomer= grp.Key ,Name = string.Join(",",grp.Select (g => g.Name))};
return d.ToList();
}
}
I have the following responses from the API. How can I group them into the following structure?
Student[]
- Name
- Classes[]
- ClassName
- ClassId
- ClassCategories[]
- CategoryName
- CategoryWeight
- Assignments[]
- AssignmentName
- Score
I was managed to group them until the "Classes" level but unable to get the ClassCategories for each of the classes
var data = (from result in results
group result by new { result.StudentId, result.FirstName, result.LastName, result.MiddleInitial }
into StudentGroup
select new GroupedStudent
{
StudentId = StudentGroup.Key.StudentId,
FullName = string.Format("{0} {1} {2}", StudentGroup.Key.FirstName, StudentGroup.Key.MiddleInitial, StudentGroup.Key.LastName).Replace(" ", " "),
Classes = from result in results
group result by new { result.ClassId, result.ClassName } into ClassGroup
select new groupedClass
{
ClassName = ClassGroup.Key.ClassName,
ClassId = ClassGroup.Key.ClassId,
ClassCategories = ...
})
}).ToList();
Can anyone please assists me? Thank you.
First, you have make ClassGroup from StudentGroup not from results.
Classes = from s in StudentGroup group result by new { s.ClassId, s.ClassName } into ClassGroup
The complete linq query is as follows:
var data =
(from result in results
group result by new { result.StudentId, result.FirstName, result.LastName, result.MiddleInitial } into StudentGroup
select new
{
StudentId = StudentGroup.Key.StudentId,
FullName = string.Format("{0} {1} {2}", StudentGroup.Key.FirstName, StudentGroup.Key.MiddleInitial, StudentGroup.Key.LastName).Replace(" ", " "),
Classes = (from s in StudentGroup
group s by new { s.ClassId, s.ClassName } into ClassGroup
select new
{
ClassId = ClassGroup.Key.ClassId,
ClassName = ClassGroup.Key.ClassName,
ClassCategories = (from c in ClassGroup
group c by new { c.CategoryName, c.CategoryWeight } into CategoryGroup
select new
{
CategoryName = CategoryGroup.Key.CategoryName,
CategoryWeight = CategoryGroup.Key.CategoryWeight,
Assignments = (from ct in CategoryGroup
group ct by new { ct.AssignmentName, ct.Score } into AssingnmentGroup
select new
{
AssignmentName = AssingnmentGroup.Key.AssignmentName,
Score = AssingnmentGroup.Key.Score
}).ToList()
}).ToList()
}).ToList()
}).ToList();
For example, if you want to access to the first Assignment's score, you can get it like this:
var student = data.FirstOrDefault();
var score = student.Classes[0].ClassCategories[0].Assignments[0].Score;
This is usually how I do It.
Create a class to store your data
Create a list of that class type
In your case instead of string dataRow maybe you can use a sub class
.
// get data from webservice
var json = webClient.DownloadString(url);
var values = JsonConvert.DeserializeObject<JArray>(json);
// create a list to save all the element
List<myClass> classList = new List<myClass>();
// process every row
foreach (string dataRow in values)
{
string[] dataField = dataRow.Split(',');
// have a constructor to assign each value to this element
myClass ctROW = new myClass(dataField);
classList.add(ctROW );
I am doing following and it works:
var resultsHeader = (from r in o select new {
OrderID = r.OrderID,
subtotal = r.SubTotal,
city = r.orderAddress.BilltoCity
}).Distinct().ToList();
Look at the city = r.orderAddress.BilltoCity Line, is there any way i can populate the entire object there...like this
var resultsHeader = (from r in o select new {
OrderID = r.OrderID,
subtotal = r.SubTotal,
Address = r.orderAddress
}).Distinct().ToList();
Basicly, I want to store entire OrderAddress Object into Address property, however it does not come out as Distinct object.
You can either use DistinctBy from moreLINQ:
var resultsHeader = (from r in o select new {
OrderID = r.OrderID,
subtotal = r.SubTotal,
city = r.orderAddress.BilltoCity
}).DistinctBy(x => new { x.OrderID, x.subtotal }).ToList();
or GroupBy, which is part of LINQ already:
var resultsHeader = (from r in o
group r by new { r.OrderIs, r.SubTotal } into g
select new {
g.Key.OrderID,
g.Key.SubTotal,
Address = g.First().orderAddress
}).ToList()
UPDATE
Or, you can implement Equals and GetHashCode on your Address class and use Distinct as you do now.