C# EntityFramework Join - c#

I would like to join the results of 2 entities based on the quantities. Here's what I have...
Order Ticket #1
OrderID CustomerID ItemID Description POS# Cost Quantity
1 1 1 Apples 111 1.25 3
1 1 2 Oranges 222 1.12 5
1 1 3 Bananas 333 1.17 5
Order Ticket #2
OrderID CustomerID ItemID Description POS# Cost Quantity
2 1 1 Apples 111 1.25 7
2 1 2 Oranges 222 1.12 2
2 1 3 Bananas 333 1.17 5
Here is the code I use to get each ticket:
public OrderEntity getOrder(int orderId)
{
var data = from c in Orders
where c.OrderID == orderId
select c;
return data;
}
How would I write the LINQ code to combine the 2 tickets so I get a Sum of the quantities? It should look like this...
Order Tickets #1 and #2
CustomerID ItemID Description POS# Cost Quantity
1 1 Apples 111 1.25 10
1 2 Oranges 222 1.12 7
1 3 Bananas 333 1.17 10
It seems like I should be able to do something like so...
public List<OrderEntity> getCustomerOrders(int customerId)
{
var data = from c in Orders
where c.CustomerID == customerId
select c;
return data.ToList();
}
The problem is I cannot figure out the grouping. There is a lot of info about there about how to write the EF code for grouping, but I'm not sure if I should be grouping on CustomerID or on the Quantity. Any tips on how to do the grouping here would be greatly appreciated.

You should group by CustomerID and ItemID:
Try something like this:
public List<OrderEntity> getCustomerOrders(int customerId)
{
var data = from c in Orders
where c.CustomerID == customerId
group c by new { c.CustomerID, c.ItemID } into g
select new OrderEntity () {
CustomerID = g.Key.CustomerID,
ItemID = g.Key.ItemID,
Quantity = g.Sum(x => x.Quantity)
};
return data.ToList();
}
I'm not sure how you define your data, but if you need to have Description POS, Cost in your result, try:
public List<OrderEntity> getCustomerOrders(int customerId)
{
var data = from c in Orders
where c.CustomerID == customerId
group c by new { c.CustomerID, c.ItemID,c.Description,c.POST,c.Cost } into g
select new OrderEntity () {
CustomerID = g.Key.CustomerID,
ItemID = g.Key.ItemID,
Quantity = g.Sum(x => x.Quantity),
Description = g.Key.Description,
POST = g.Key.POST,
Cost = g.Key.Cost
};
return data.ToList();
}

Related

Join with last record of details table

Please consider these two tables in my database:
Header:
Id Name
-------------------------------
1 London
2 Berlin
3 Paris
and Details:
Id HeaderId Amount YearMonth
--------------------------------------------------------------------
1 1 1000 2010-01
2 1 2000 2010-05
3 2 3000 2015-04
4 2 2700 2017-12
5 2 4500 2016-10
6 2 7000 2011-09
7 1 3000 2009-05
I want Header records with related Last Details record. For example:
HeaderId HeaderName Amount
----------------------------------------------------
1 London 2000
2 Berlin 2700
3 Paris Null
I wrote this query for Inner Join version (But I want Outer Join version):
from h in Header
join d in Details
on h.Id equals d.HeaderId
select new
{
HeaderId = h.Id,
HeaderName = h.Name,
Amount = (Details.Where(k=>k.HeaderId == h.Id).OrderBy(m=>m.YearMonth).LastOrDefault() == null ? null : Details.Where(k=>k.HeaderId == h.Id).OrderBy(m=>m.YearMonth).LastOrDefault().Amount,
}
and I got this error:
System.NotSupportedException: LINQ to Entities does not recognize the method 'Details.LastOrDefault()Details' method, and this method cannot be translated into a store expression.
How can I get above result?
thanks
This query should return desired result:
from h in Header
from d in Details.Where(d => d.HeaderId == h.Id)
.OrderByDescending(d => d.YearMonth)
.Take(1)
.DefaultIfEmpty()
select new
{
HeaderId = h.Id,
HeaderName = h.Name,
Amount = d.Amount
}
You should change your code as :
Amount = Details.Where(k=>k.HeaderId == h.Id).OrderByDescending(m => m.YearMonth).FirstOrDefault(o=>o.Amount);

EF duplicate values in secondary table

I'm developing a web application using Entity Framework.
I need do a select and pass values for an Ilist but it's returns duplicate values.
IQueryable<establishmentInfo> filter = (from x in db.establishments
join t in db.establishment_categories on x.id equals t.establishment
join q in db.categories on t.category equals q.id
where (x.name.ToUpper().Contains(search.ToUpper()))
select new establishmentInfo
{
id = x.id,
name = x.name,
id_category = q.id,
category = q.name,
});
IList<establishmentInfo>establishments = filter.ToList();
Establishment table
id name email
---------------------------
1 AAA a#a.com
2 BBB b#b.com
Establishment_categories
id establishment category
-------------------------------
1 1 1
2 1 2
3 2 1
Categories
id name
---------------------
1 alpha
2 beta
The problem is that return 2 establishments, one with category 1 and other with category 2. I need remove one of these.
Can anyone help?
As #NetMage said,your linq statement should return two values that are not repeated.
We can see that there are two records with establishment set to 1 in your Establishment_categories table. You can check your establishments. The id_category should be 1, the category should be alpha, the other should be id_categoryis 2, and the category should be beta.
You can see below image:
If you only want to get the first data of establishments, you can write the code as follows:
IQueryable<Establishment> filter = (from x in _context.Establishments
join t in _context.Establishment_Categories on x.Id equals t.EstablishmentId
join q in _context.Categories on t.CategoryId equals q.Id
where x.Name.ToUpper().Contains(search.ToUpper())
select new Establishment
{
Id = x.Id,
Name = x.Name,
CategoryId = q.Id,
CategoryName = q.Name,
}).Take(1);
List<Establishment> establishments = filter.ToList();
Result:
By the way, assuming that there are duplicates in your returned data, you can add the .Distinct() method after your linq to remove duplicates.

LINQ Query multiple orderby of joined tables

I have following LinQ query
var CGTABLE = (from cg in DbContext.CGTABLE
join tcg in DbContext.TCGTABLE on new { cg.CGroupId } equals new { tcg.CGroupId }
where tcg.TId == TId
select new {
CGroupId = cg.CGroupId,
CGroupCode = cg.CGroupCode,
Description = cg.Description,
C = cg.C,
DisplayOrder = cg.DisplayOrder
}).ToList();
CGTABLE = CGTABLE.OrderBy(g => g.DisplayOrder).ThenBy(g => g.C.OrderBy(c => c.CCode)).ToList();
which runs fine, but it is not doing second orderby using ThenBy ThenBy(g => g.C.OrderBy(c => c.CCode) What am I missing?
Sample data for better understanding.
Data in Tables
2
1
2
4
3
1
4
5
2
1
3
3
1
Should output after both outer and inner list ordered by
1
1
2
3
4
2
1
2
4
5
3
1
3
But Currently it is showing
1
4
5
2
1
2
1
2
4
3
3
3
1
You didn't want to order the main list, you are looking for a way to order inner list inside of outer one, I think.
So below code will do it for you:
var CGTABLE = (
from cg in DbContext.CGTABLE
join tcg in DbContext.TCGTABLE on new { cg.CGroupId } equals new { tcg.CGroupId }
where tcg.TId == TId
select new {
CGroupId = cg.CGroupId,
CGroupCode = cg.CGroupCode,
Description = cg.Description,
C = cg.C.OrderBy(x => x.CCode),
DisplayOrder = cg.DisplayOrder
}).ToList();
CGTABLE = CGTABLE.OrderBy(g => g.DisplayOrder).ToList();

Entity Framework - .Include doesn't load all records

I have this a database with these entities:
public class User
{
public GUID UserId { get; set;}
public IEnumerable<Item> items { get; set;}
}
public class Item
{
public GUID ItemId { get; set;}
public GUID ownerId { get; set;}
public int boughtCount{ get; set;}
}
I need to return the list of users that have items ordered by the items bought the most.
So for example if we have this users:
A: userId: ..
items: 1. itemId: .. | boughtCount: 2
2. itemId: .. | boughtCount: 1
B: userId: ..
items: 1. itemId: .. | boughtCount: 7
C: userId: ..
items: 1. itemId: .. | boughtCount: 3
D: userId: ..
items: none
The query needs to return the users in the following order: B,C,A (D is not returned as he doesn't have any items)
I am using the following query:
users = await _context.Items.OrderByDescending(c => c.BoughtCount)
.Join(_context.Users,
i => i.OwnerId,
u => u.Id,
(i, u) => new { i, u })
.OrderByDescending(x => x.i.BoughtCount)
.Select(x => x.u)
.Distinct()
.Skip(skip)
.Take(take)
.Include(u => u.Items)
.ToListAsync();
This query returns the users in the correct order, but my problem is that for each user it returns maximum of 15 of the items he has, so if for example user A would have 30 items, I will only get his first 15.
What is this 15 items limit?
Am I doing something that cause this limit to come or it's just "hard coded" somewhere?
If so, how do I remove/change the limit?
Note: My sql database is hosted in Azure.
UPDATE:
This is the generated sql query from my linq query:
SELECT [I].[ItemId], [I].[ownerId], [I].[boughtCount]
FROM [Items] AS [I]
INNER JOIN (
SELECT DISTINCT [t0].*
FROM (
SELECT DISTINCT [u].[UserId]
FROM [Items] AS [I]
INNER JOIN [User] AS [u] ON [c].[ownerId] = [u].[UserId]
ORDER BY [u].[UserId]
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
) AS [t0]
) AS [u] ON [I].[ownerId] = [u].[UserId]
Thanks!

How to select from 3 tables in a series using Linq?

I have 3 tables:
Degree(Id int(PK), DegreeName string)
1 Bachelor
2 Master
3 PhD
Track(Id int(PK), DegreeId int(FK), TrackName string)
1 2 Engineer
2 1 Technician
3 1 Assistant
4 2 Physicist
5 3 Doctor
Group(Id int(PK), TrackId int(FK), GroupName string)
1 4 Group1
2 3 Group2
3 1 Group3
4 3 Group4
5 2 Group5
there is a one to many relation between Degree and Track, and another one to many relation between Track and Group.
I have this class:
Public class DegreeDetails
{
public List<Track> TrackList { get; set; }
public List<Group> GroupsList { get; set; }
}
to get all tracks these belong to bachelor degree, which are technician and assistant, I use this code:
In the controller I use this code:
DegreeDetails MyView = new DegreeDetails();
MyView.TrackList = entity.Track.Where(s => s.DegreeID == 1).ToList();
how to get a Group List of all groups these study tracks belong to bachelor degree, which should be Group2, Group4 and Group5.
Probably the best thing to do is to join these tables. You could create a view in your database, or you can join tables using Linq.
This should work:
MyView.GroupList = (from d in entity.Degree
join t in entity.Track on d.Id equals t.DegreeId
join g in entity.Group on t.Id equals g.TrackId
where d.Id == 1
select g).Distinct().ToList();
UPDATE If you want to use lambda exp, try this:
MyView.GroupList = entity.Degree.Where(d => d.Id == 1)
.Join(entity.Track, d => d.Id, t=> t.DegreeId, (d, t) => t)
.Join(entity.Group, t => t.Id, g => g.TrackId, (t, g) => g)
.Distinct().ToList();
You should join tracks with groups:
var groupList = entity.Track.Where(s=>s.DegreeID == 1).Join(entity.Group, t=>t.Id, g=>g.TrackId, (t,g)=>g).ToArray();

Categories

Resources