Linq Group by relative entites - c#

My scenario: Users will be able to create lists and add items to these lists. What I want to do is to find the items in the lists created by the users at most.
Item Entity
public class Item:BaseEntity
{
public string Name { get; set; }
public decimal Price { get; set; }
public decimal DiscountedPrice{ get; set; }
public virtual ICollection<ItemList> ItemLists { get; set; }
}
Item List Entity
public class ItemList:BaseEntity
{
public string Name { get; set; }
public string Description { get; set; }
public int UserId { get; set; }
public ICollection<Item> Items { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
}
User Entity
public class User:BaseEntity
{
public string Name { get; set; }
public string Surname { get; set; }
public string Gsm { get; set; }
public string Email { get; set; }
public virtual ICollection<ItemList> ItemLists{ get; set; }
}
my DTO
public class TopItemsForUsers
{
[BsonRepresentation(BsonType.ObjectId)]
[BsonId]
public string ItemId { get; set; }
public string UserId { get; set; }
public int Quantity { get; set; }
}
My Item repository
var query = _context.Items.Include(l => l.ItemLists)
.GroupBy(g => g.ItemLists)
.Select(z => new TopItemsInLists { ItemId = z.Key.ToString(), Quantity = z.Count() })
.OrderByDescending(z => z.Quantity)
.Take(10);
I want to get products that are very present in users' lists
Where am I doing wrong? If anyone has any other suggestions

Try this query. I hope I understand question correctly.
var query =
from u in _context.Users
from il in u.ItemLists
from i in il.Items
group i by new { UserId = u.Id, ItemId = i.Id } into g
select new TopItemsInLists
{
UserId = g.Key.UserId.ToString(),
ItemId = g.Key.ItemId.ToString(),
Quantity = g.Count()
};
query = query
.OrderByDescending(z => z.Quantity)
.Take(10);

Related

EF Core join on sub table

I have three classes set up like this:
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<UserItem> UserItems { get; set; }
}
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<UserItem> UserItems { get; set; }
}
public class UserItem
{
public int ID { get; set; }
public int UserID { get; set; }
public int ItemID { get; set; }
}
Entity Framework generates the tables in the SQL Server database with the correct foreign keys. I can query the Item and User to get the UserItem collections within like this:
var a = context.DBUser.Include(s => s.UserItems);
var b = context.DBItem.Include(s => s.UserItems);
What I am not happy about is how I get from the User to the Item. In SQL I would do something like this
SELECT * FROM Users U
LEFT JOIN UserItems UI
ON U.ID = UI.UserID
LEFT JOIN Items I
ON UI.ItemID = I.ID
In C# I've needed to resort to this:
var c = from user in _context.DBUsers
join userItem in _context.DBUserItems
on user.ID equals userItem.UserID into ui
from userItem in ui.DefaultIfEmpty()
join item in _context.DBItems
on userItem.ItemID equals item.ID into i
from item in i.DefaultIfEmpty()
select new
{
user,
userItem,
item
};
Which given there should already be relationships between the tables in EF doesn't feel right
You need to add navigations to UserItem also:
public class UserItem
{
public int ID { get; set; }
public int UserID { get; set; }
public int ItemID { get; set; }
public User User { get; set; }
public Item Item { get; set; }
}
Then your query can be like this:
var users = context.DBUser
.Include(x => x.UserItems)
.ThenInclude(x => x.Item);
Also note that if you are using .NET 5, the UserItem "join entity" can be omitted altogether:
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Item> Items { get; set; }
}
Which would simplify your query:
var users = context.DBUser.Include(x => x.Items);

Call ICollection in ICollection with Lambda Expression

I want a lambda expression, that when i call a Company from database with id 1030 to bring me Companys info, a list with all the cars that company has and a list of all images that related to each car (each car has 4 images).
Structure of my classes:
public partial class Companies
{
public int CompanyId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Tel { get; set; }
public string Logo { get; set; }
public int? Owner { get; set; }
public int? Address { get; set; }
public int? Publish { get; set; }
public ICollection<Cars> Cars { get; set; }
}
public partial class Cars
{
public int CarId { get; set; }
public string Manufacturer { get; set; }
public string Model { get; set; }
public string Year { get; set; }
public string Description { get; set; }
public decimal? Price { get; set; }
public int? CarCatId { get; set; }
public int? CompanyId { get; set; }
public int? CharacteristicId { get; set; }
public ICollection<CarImages> CarImages { get; set; }
}
public partial class CarImages
{
public int CarImagesId { get; set; }
public string Image { get; set; }
public int? CarId { get; set; }
public Cars Car { get; set; }
}
As you can see in Company class, I have a reference to Cars class as ICollection, and the same thing in Cars class with CarImages.
I've try lot of things including those:
var compInfo = _context.Companies.SelectMany(cr => cr.Cars.SelectMany(i =>i.CarImages.Where(car => car.CarId == car.Car.CarId))).ToList();
var compInfo2 = _context.Companies.Include(a => a.AddressNavigation).Include(cr =>cr.Cars.).FirstOrDefault(c => c.CompanyId == id);
The 2nd brings me the info of company (and it's address) and the list of the cars (which is the half success) but not the images..
The 1st just brings me a list all the info of images table.
I found the solution.
//Get the Company with id == 1030.
var x = _context.Companies.Include(a => a.AddressNavigation).Include(c => c.Cars).Where(c => c.CompanyId == id).FirstOrDefault();
//Get the Car ICollection and include the CarImages ICollection depending on CompanyID.
var y = _context.Cars.Include(img => img.CarImages).Where(cr => cr.CompanyId == x.CompanyId).ToList();
//Now each Car in our Cars list has a list of CarImages related to each car. Finaly pass our data to our Company var(x) and send it to View.
x.Cars = y;
return View(x);

Cannot convert type IEnumerable to List C#

I'm trying to bring a listing to frontEnd.
I'm using mongoDb. My mongodb has a colletion called Employee. Employee has the following attribute
public class EmployeeViewModel
{
[BsonId(IdGenerator = typeof(StringObjectIdGenerator))]
public string ownerId { get; set; }
public string atributeChange { get; set; }
public PersonalDataViewModel personalData { get; set; }
public AddressViewModel address { get; set; }
public List<EmailsViewModel> emails { get; set; }
public SyndicateViewModel syndicate { get; set; }
public List<DependentsViewModel> dependents { get; set; }
public List<PhoneViewModel> phone { get; set; }
public List<BankViewModel> bank { get; set; }
public AttributesViewModel attributes { get; set; }
public List<BenefitsViewModel> benefits { get; set; }
public TransportViewModel transport { get; set; }
public List<AttachmentsViewModel> attachments { get; set; }
public List<DocumentsViewModel> documents { get; set; }
public List<DocumentsImagesViewModel> DependentsDocuments { get; set; }
public List<AttachmentsViewModel> DependentsAttachments { get; set; }
public List<BenefitsViewModel> DependentsBenefits { get; set; }
}
In this Model, I have an attribute called: public List <DocumentsImagesViewModel> DependentsDocuments {get; set; }:
public class DocumentsViewModel
{
[BsonId]
public string ownerId { get; set; }
public string id { get; set; }
public string dependentId { get; set; }
public string number { get; set; }
public DateTime expiration { get; set; }
public List<DocumentsImagesViewModel> images { get; set; }
public List<DocumentPropertiesViewModel> properties { get; set; }
public DocumentTypeViewModel type { get; set; }
}
I'm trying to bring benefits that contain the depedentID equal of the parameter. When I use this method, it has an error that can not be converted. IEnumerable to List C #
public async Task<List<Documents>> GetDocument(string ownerId, string dependentId)
{
var query = from employee in _employee.AsQueryable()
where employee.ownerId == ownerId
select new Employee()
{
DependentsDocuments = employee.DependentsDocuments.Where(x => x.dependentId == dependentId)
};
return query.ToList();
}
What is the best way to get this data? this filter?
I used this question as a reference: Mongodb C# driver return only matching sub documents in array
LINQ's .Where returns IEnumerable<T>, your model expects a List<T>, you can either change your model to IEnumerable<T> or you can change this line of code:
DependentsDocuments = employee.DependentsDocuments
.Where(x => x.dependentId == dependentId)
to this:
DependentsDocuments = employee.DependentsDocuments
.Where(x => x.dependentId == dependentId)
.ToList()
changing your code to this one maybe it work:
public async Task<List<Documents>> GetDocument(string ownerId, string dependentId)
{
var query = (from employee in _employee.AsQueryable()
where employee.ownerId == ownerId
select new Employee()
{
DependentsDocuments = employee.DependentsDocuments.Where(x => x.dependentId == dependentId).ToList()
}).ToList();
return query.ToList();
}

Generate All customers total Sales Statement - using Linq

I have database with Customers.cs, Sales Here I'm stuck how to Generate All customers total Sales Statement.
Actually I want to calculate All Customers Account Receivables. if I will get that how to generate customers total sales I can generate account receivable report.
Sale.cs
public partial class Sale
{
public string SaleId { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public string CustomerId { get; set; }
public string Description { get; set; }
public Nullable<double> Amount { get; set; }
public virtual Customer Customer { get; set; }
}
Customer.cs
public partial class Customer
{
public string CustId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string TownCity { get; set; }
public int Contact { get; set; }
}
I want to get result like this..
Town/City CustomerName TotalSale
You can do it using GroupBy:
var res = _dbContext.Sales
.GroupBy(s => s.CustomerId)
.Select(s => new { CustomerId = s.Key, TotalSales = s.Sum(a => a.Amount) })
.ToList();

Get row count using group by in entityframework

I have a TheaterMovieShowTime entity in that entity I want to get the row count by grouping on a particular column say TheaterMovieDetailID .
Here is my entity :
public class TheaterMovieShowTime
{
public int TheaterMovieShowTimeID { get; set; }
public int TheaterMovieDetailID { get; set; }
public int TheaterShowTimeID { get; set; }
public virtual TheaterMovieDetail TheaterMovieDetails { get; set; }
public virtual TheaterShowTime TheaterShowTime { get; set; }
}
Here is my TheaterMovieDetail entity:
public class TheaterMovieDetail
{
public int TheaterMovieDetailID { get; set; }
public int TheaterID { get; set; }
public int MovieID { get; set; }
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public virtual Movie Movie { get; set; }
public virtual Theater Theater { get; set; }
public virtual ICollection<TheaterMovieShowTime> TheaterMovieShowTimes { get; set; }
}
I try this :
var p = _theaterMovieShowTimeService.GetAllTheaterMovieShowTime()
.GroupBy(x => x.TheaterMovieDetailID)
.Select(x => new TheaterMovieShowTimeSummaryViewModel
{
TheaterName = x.FirstOrDefault().TheaterMovieDetails.Theater.TheaterName,
MovieName = x.FirstOrDefault().TheaterMovieDetails.Movie.MovieName,
NoOfShows=???????? // get the no of rows here
});
How do I get NoOfShows here that is no of rows grouped by TheaterMovieDetailID .
Would appreciate any help offered. Let me know if you need any other information to help answer this question
Use linq Count() function:
var p = _theaterMovieShowTimeService.GetAllTheaterMovieShowTime()
.GroupBy(x => x.TheaterMovieDetailID)
.Select(x => new TheaterMovieShowTimeSummaryViewModel
{
TheaterName = x.FirstOrDefault().TheaterMovieDetails.Theater.TheaterName,
MovieName = x.FirstOrDefault().TheaterMovieDetails.Movie.MovieName,
NoOfShows= x.Count() // get the no of rows here
});

Categories