Entity Framework LINQ - c#

How do I find which clubs have the most players in query. So the query would contain all the clubs that have the most players. For example if first club has 3 players, second club has 5 players and third club also has 5 players then there would be second and third club in the query. And i need to return list of the clubs.
public List<Club> ClubWithMostPlayers()
{
using (var context = new dataContext())
{
var query = ?????
return query.ToList();
}
}
These are classes that i use
public class Player
{
public int PlayerId { get; set; }
public string name { get; set; }
public string surname { get; set; }
public int yearOfBirth { get; set; }
public virtual List<PlayerClub> playerClub { get; set; }
}
public class Club
{
public int ClubId { get; set; }
public string name { get; set; }
public string stadium { get; set; }
public int yearOfConstruction { get; set; }
public virtual List<PlayerClub> playerClub { get; set; }
}
public class PlayerClub
{
public int PlayerClubId { get; set; }
public int PlayerId { get; set; }
public int ClubId { get; set; }
public virtual Player player { get; set; }
public virtual Club club { get; set; }
public int from { get; set; }
public int to { get; set; }
public int appearances { get; set; }
}
I know how to do it in SQL, but not in LINQ
Thank you for help

How about dividing your query into two parts.
// get number of maximum number of players in one club
var count = context.Clubs.Select(c => c.playerClub.Count()).Max();
// get clubs with specific number of players
var query = context.Clubs
.Where(c => c.playerClub.Count() == count);

Related

Asp.net core mvc ViewModel with 2 Models

I'm building a feature with a jquery datatable, the idea is to have a list of stores in the parent row, and then when expanding the parent to list all the licensed terminals in child rows that are linked to the store parent row by a StoreLicenseId column. The issue I am having is that I have a ViewModel with two models, one for the list of stores and one for the licensed terminals. I'm busy building the method into my controller, my problem is in the second part of the method where I new up "StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()", all the references to tl.terminalId and tl.Terminalname. I get this error "StoreListViewModel does not contain a definition for TerminalID and no accessible extension method". I can see why this is happening, so my question really is, how do I include this "second" TerminalListViewModel into my method to form part of the query ?
ViewModel
public partial class StoreListViewModel
{
public List<TerminalListViewModel> StoreLicenseDetails { get; set; } = null!;
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
[DisplayName("Store Name")]
public string StoreName { get; set; } = null!;
[DisplayName("App One Licenses")]
public int QtyAppOneLicenses { get; set; }
[DisplayName("App Two Licenses")]
public int QtyAppTwoLicenses { get; set; }
[DisplayName("Date Licensed")]
public DateTime DateLicensed { get; set; }
[DisplayName("Licensed Days")]
public int LicenseDays { get; set; }
[DisplayName("Is License Active")]
public bool LicenseIsActive { get; set; }
}
public partial class TerminalListViewModel
{
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
public Guid TerminalId { get; set; }
public string TerminalName { get; set; } = null!;
public string LicenseType { get; set; } = null!;
public int TerminalLicenseDays { get; set; }
public DateTime DateLicensed { get; set; }
public bool LicenseIsActive { get; set; }
public bool IsDecommissioned { get; set; }
public DateTime LastLicenseCheck { get; set; }
}
Controller Method
//sl = StoreList
//tl = TerminalList
public IEnumerable<StoreListViewModel> GetStoreList()
{
return GetStoreList().GroupBy(sl => new { sl.StoreLicenseId, sl.StoreName, sl.QtyAppOneLicenses,
sl.QtyAppTwoLicenses, sl.DateLicensed, sl.LicenseDays,
sl.LicenseIsActive })
.Select(sl => new StoreListViewModel()
{
StoreName = sl.Key.StoreName,
QtyAppOneLicenses = sl.Key.QtyAppOneLicenses,
QtyAppTwoLicenses = sl.Key.QtyAppTwoLicenses,
DateLicensed = sl.Key.DateLicensed,
LicenseDays = sl.Key.LicenseDays,
LicenseIsActive = sl.Key.LicenseIsActive,
StoreLicenseId = sl.FirstOrDefault().StoreLicenseId,
StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()
{
StoreLicenseId = tl.StoreLicenseId,
TerminalId = tl.TerminalId,
TerminalName = tl.TerminalName,
}).ToList()
}).ToList();
}
Based on the error,I suppose your GetStoreList() method returns List<OrderListViewModel> ,but your OrderListViewModel doesn't contains properties of TerminalListViewModel,So you got the error
GetStoreList() method should return List<SourceModel>( Source is the model which contains all the properties of StoreListViewModel and TerminalListViewModel)
For example,the link your provided:Multiple child rows in datatable, data from sql server in asp.net core
public class OrderList
{
//source of properties of OrderListViewModel(parent rows)
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
//source of properties of OrderListDetailViewModel(child rows)
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
public class OrderListViewModel
{
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
public List<OrderListDetailViewModel> OrderListDetails { get; set; }
}
public class OrderListDetailViewModel
{
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
Orderlist contains all columns OrderListViewModel and OrderListDetailViewModel needs.
When it comes to your case,you should
create 3 models (source,parentrow,childrows)
model for parentrows contains the properties
StoreLicenseId,StoreName, QtyAppOneLicenses,QtyAppTwoLicenses, DateLicensed, LicenseDays,LicenseIsActive
and model for childrows contains the other properties of source model
If you still have questions,please show the data you pulled form db,and I'll write a demo for you

Is there a way I can limit the number of group members of a group using blazor?

I have two related tables which represent a one to many relationship; that is the group table and the group member table. One group can have only up to five group members. How would I limit this number to only five so that never more than five members can be added to one group?
The following are my C# classes.
public class Group
{
[Key]
public int GroupId { get; set; }
public string GroupName { get; set; }
public int GroupNumber { get; set; }
public string Product_Service { get; set; }
public string BusinessLocation { get; set; }
public List<GroupMember> GroupMembers { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
public List<Loan> Loans { get; set; }
}
public class GroupMember
{
[Key]
public int MemberId { get; set; }
public int MemberNumber { get; set; }
[Required, RegularExpression(#"^\d{6}\/\d{2}\/\d{1}$", ErrorMessage = "Please enter a valid NRC. xxxxxx/xx/x")]
public string Nrc { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string PhoneNumber { get; set; }
public int GroupId { get; set; }
public Group Group { get; set; }
I Think that you want to add your own validation:
public class CountGroupMembersAttribute : ValidationAttribute
{
private readonly int count;
public CountGroupMembersAttribute(int count)
{
this.count = count;
}
protected overrride ValidationResult IsValid(object value, ValidationContext context)
{
List<GroupMember> groups= value as List<GroupMember>;
if(groups == null)
return validation.Success;
if(groups.Count > 5)
{
return new ValidationResult("the following property has been exceeded the limit", new[] { context.MemberName });
}
}
}
Then use it like this:
[CountGroupMembers(count:5)]
public List<GroupMember> GroupMembers { get; set; }

EF6 - Many-to-One Relationship not working

I have Products, Sub products, and more tables. You can see in the code, relationship not working I want it Product Class relationship with SubProduct but always the collection count is 0.
Product Class:
[Key]
public int Id { get; set; }
public bool Status { get; set; } = true;
public string StockCode { get; set; }
public int StockDecrease { get; set; }
public string Name { get; set; }
public int Amount { get; set; }
public int Desi { get; set; }
public string Barcode { get; set; }
public long Gtin { get; set; }
public string InvoiceName { get; set; }
public string EInvoiceName { get; set; }
public string Subtitle { get; set; }
public byte Kdv { get; set; }
public virtual Category Category { get; set; }
public string Description { get; set; }
public virtual ICollection<SubProduct> SubProducts { get; set; }
public virtual ICollection<ProductVariant> ProductVariants { get; set; }
Sub Product Class:
public int Id { get; set; }
public int ProductId { get; set; }
public virtual Product Product { get; set; }
public string StockCode { get; set; }
public virtual ProductBrand Brand { get; set; }
public virtual Company Company { get; set; }
public Abstract.Marketplace Marketplace { get; set; }
public string Barcode { get; set; }
public string Title { get; set; }
public string SubTitle { get; set; }
public bool IsConnected { get; set; }
public decimal Price { get; set; }
public decimal PriceDiscount { get; set; }
public string Description { get; set; }
public virtual ICollection<SubProductVariant> SubProductVariants { get; set; }
Repository Base:
public async System.Threading.Tasks.Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> filter)
{
await using var context = new TContext();
return await context.Set<TEntity>().Where(filter).SingleOrDefaultAsync();
}
Make sure to add using System.Data.Entity; to get the version of Include that takes in a lambda.
using System.Data.Entity;
query.Include(x => x.SubProducts)
and for more use ThenInclude or Include extention methods.
To define a method on the repository for this, you can use this example:
public static IQueryable<TSource> GetIQueryableWithIncludes<TSource>(Expression<Func<TSource, object>>[] includeProperties, IQueryable<TSource> result)
{
var newResult = result;
if (includeProperties.Any())
{
foreach (var includeProperty in includeProperties)
{
newResult = newResult.Include(includeProperty);
}
}
return newResult;
}
You can now pass a list of lamba expression like p => p.SubProjects to specify what you want to include.
You can further hide this by making an GetAll method that hides these includes from the outside user of your Domain
I would suggest to first study more about how to handle related entities.
You basically need to tell EF to load them in.
See documentation
Simplest example would something like this:
// Load all products.
var products= context.Products
.Include(b => b.SubProducts)
.ToList();
I solved with .Include() thanks for helping.
public async System.Threading.Tasks.Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> filter, Expression<Func<TEntity,object>> include=null)
{
await using var context = new TContext();
return await context.Set<TEntity>().Where(filter).Include(include).SingleOrDefaultAsync(filter);
}

Querying object with list of lists of lists

I want to query the database and get a sport object containing all inner lists, but for some reason I'm missing, the select only goes 2 levels deep in lists, any deepers and the lists property have a value of null,
example of the structure
public class Sports
{
public int id { get; set; }
public string name { get; set; }
public List<League> leagues { get; set; }
}
public class League
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public List<Team> teams { get; set; }
}
public class Team
{
public int id { get; set; }
public string name { get; set; }
public string successrate { get; set; }
public List<Player> players { get; set; }
}
public class Player
{
public int id { get; set; }
public string name { get; set; }
public int age { get; set; }
}
I created property in MyAppContext file as this
public DbSet<Sports> sports { get; set; }
now when I call an item using select or linq or any other way I tried, the sport object is always 2 Dimensional, meaning it doesn't go deeper than two levels in nested lists! Example of result using var sport=db.Sports.First() the result is {"id":1,"name":"Football","leagues":null} or if I used select()
var sportQuery = db.sports.Select(
s=>new Sports(){
id=s.id,
leagues=s.leagues,
name=s.name
}).First();
I still don't get full information {"id":1,"name":"Football","leagues":[{"id":1,"name":"fc","description":"Some Leauge","teams":null},{"id":2,"name":"al","description":"League","teams":null}]}
why is that! and how to get full object like this
{"id":1,"name":"Football","leagues":[{"id":1,"name":"fc","description":"Some Leauge","teams":[{"id":1,"name":"real madrid","successrate":null,"players":[{"id":1,"name":"Cristiano Ronaldo","age":21},{"id":2,"name":"Iniesta","age":38}]},{"id":2,"name":"Barcelona","successrate":null,"players":[{"id":1,"name":"Cristiano Ronaldo","age":21},{"id":2,"name":"Iniesta","age":38}]}]},{"id":2,"name":"al","description":"League","teams":[{"id":1,"name":"real madrid","successrate":null,"players":[{"id":1,"name":"Cristiano Ronaldo","age":21},{"id":2,"name":"Iniesta","age":38}]},{"id":2,"name":"Barcelona","successrate":null,"players":[{"id":1,"name":"Cristiano Ronaldo","age":21},{"id":2,"name":"Iniesta","age":38}]}]}]}
I've been stuck for days, Please any help would be much appreciated
Try following :
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DataBase db = new DataBase();
var sportQuery = db.sports.Select(s=> s.leagues.Select(l => l.teams.Select(t => t.players.Select(p => new {
playerid = p.id,
playerName = p.name,
playerAge = p.age,
teamId = t.id,
teamName = t.name,
teamSucessrate = t.successrate,
leagueId= l.id,
leagueName= l.name,
leagueDescription = l.description,
sportId = s.id,
sportName = s.name
}))
.SelectMany(p => p))
.SelectMany(t => t))
.SelectMany(l => l)
.ToList();
}
}
public class DataBase
{
public List<Sports> sports { get; set;}
}
public class Sports
{
public int id { get; set; }
public string name { get; set; }
public List<League> leagues { get; set; }
}
public class League
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public List<Team> teams { get; set; }
}
public class Team
{
public int id { get; set; }
public string name { get; set; }
public string successrate { get; set; }
public List<Player> players { get; set; }
}
public class Player
{
public int id { get; set; }
public string name { get; set; }
public int age { get; set; }
}
}
problem solved using Include() and thenInclude()
https://learn.microsoft.com/en-us/ef/core/querying/related-data
however, that doesn't explain why Select() only loads one list property deep, also it seems like i should be able to load object with select only or linq

LINQ query to get count of joined record

Can somebody help me out writing a LINQ query to get record that are joined? I have two models below. I want to get requirements count that belong to given project and has one or more ProjectTest joined to it.
public class ProjectTest
{
public int ProjectTestID { get; set; }
public int ProjectID { get; set; }
public String Objective { get; set; }
public String Category { get; set; }
public String SubCategory { get; set; }
public String Tags { get; set; }
public virtual ICollection<ProjectRequirement> ProjectRequirements { get; set; }
public virtual ICollection<ProjectTestStep> ProjectTestSteps { get; set; }
}
public class ProjectRequirement
{
public int ProjectRequirementID { get; set; }
public int ProjectID { get; set; }
[Display(Name = "Req No.")]
public String ProjectRequirementIDStr { get; set; }
[Display(Name = "Module")]
public String ModuleName { get; set; }
[Display(Name = "Description")]
public String Description { get; set; }
public virtual ICollection<ProjectTest> ProjectTests { get; set; }
}
I just tried to write it as follows but does not seem working.
db.ProjectRequirements
.Where(e => e.ProjectID == activeProjectID &&
e.ProjectTests
.Select(ept => ept.ProjectTestID)
.Count() > 0)
.Select(e => e.ProjectRequirementID)
.Count();
Currently you are counting the number of ProjectRequirement objects that have a given id and that have at least 1 ProjectTest.
If you want to count the amount of ProjectTests you have for a given ProjectId:
var number = db.ProjectRequirements.Where(e => e.ProjectID == activeProjectID)
.Sum(e => e.ProjectTests.Count());

Categories

Resources