I've the following piece of code to return a list of products based on category.
public IEnumerable<Product> GetProductsByCategoryId(string category_id)
{
return repository.GetAll().Where(
p => string.Equals(p.Category, category_id, StringComparison.OrdinalIgnoreCase));
}
I want to pass two parameters in the method, category and Brand.
public IEnumerable<Product> GetProductsByCategoryBrand(string category, string Brand)
{
}
What would the return method look like with category and Brand?
public IEnumerable<Product> GetProductsByCategoryBrand(string category, string Brand)
{
return repistory.GetAll().Where(
p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase)
&& string.Equals(p.Brand, brand, StringComparison.OrdinalIgnoreCase));
}
You just chain your conditions to the Where() using the && operator. If you want to match either brand or category, use ||
Related
I have these models below :
season :
public function club()
{
return $this->hasMany('App\Models\Club');
}
club :
public function season()
{
return $this->belongsTo('App\Models\Season' ,'season_id');
}
public function league()
{
return $this->belongsTo('App\Models\League' ,'league_id');
}
league :
public function club()
{
return $this->hasMany('App\Models\Club');
}
the season have column called status which take value of 'active' or empty.
the club have column of season id.
now I want to return list of clubs grouped by league id and just those which season status is active.
I created this controller which return list of clubs in active season :
public function clubs_by_active_season()
{
$season = Season::where('status','active')->first();
$season_id = $season->id;
$clubs=Club::where('season_id',$season_id)->get();
return $clubs;
}
and now I want to make them grouped by league id ,how can i do that ?
First, rename your relationship base on relation type to help you visualize, since it has one-to-many relationship, use plural name
public function clubs()
{
return $this->hasMany(Club::class);
}
Use clubs() function to build the query relationship and get the results
public function clubs_by_active_season()
{
$season = Season::where('status','active')->first();
$clubs = $season->clubs()
->get() // Get the results
->groupBy("league_id"); // Group the collection by `league_id` key
return $clubs;
}
I'm not sure if that is what you mean by "group by league_id"
I have the following many-to-many relation modelled
public class Profile
{
ICollection<Category> Categories { get; set;}
// One-To-Many
ICollection<Platform> Platforms { get; set; }
}
public class Category
{
ICollection<Profile> Profiles { get; set; }
}
public class ProfileCategory
{
public int ProfileId { get; set; }
public Profile Profile { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set;}
}
I'm using ASP.NET Core MVC and have a filter view model where a filter on some attributes on profile name and it works.
Trying to filter based on category proved much harder to implement (at least the solution isn't obvious to me :)
From the web the user can select zero, one or many categories to filter on so basically what is sent to my controller is a list of category ids.
IQueryable<Profile> query = _context.Profiles.Include(p => p.Categories).Include(p => p.Platforms);
if(string.IsNullOrEmpty(search.Name))
{
query = query.Where(p => p.Name.IndexOf(search.Name StringComparison.OrdinalIgnoreCase) > 0);
}
if(search.Categories?.Any() != null)
{
query = query.SelectMany(p => p.ProfileCategories)
.Join(search.Categories, pc => pc.CategoryId, cId => cId, (pc,_) => pc.Profile);
}
From this point the Profile object is different and other navigational properties such as Platforms is null hence breaking other parts.
How can I perform the join while retaining the original instance of Profile object. I first thought that they would be the same, but I was wrong.
Currently, EF Core JOINs are not perfect, and I recommend make two queries:
1) Select list of ProfileId (based on category list):
var profileIds = await _context.ProfileCategory
.Where(x => categoryIds.Contains(x.CategoryId)) // filtering goes here
.Select(x => x.ProfileId)
.Distinct()
.ToListAsync();
2) Select required data based on known IDs:
var result = await _context.Profiles
.Include(p => p.Categories).Include(p => p.Platforms)
.Where(x => profileIds.Contains(x.ProfileId))
.ToListAsync();
Yes, this is two queries instead one, but two simple queries, easily optimized using indexes.
I want to list all categories of all published posts. But I would like to display categories just once.
The Post class has a prop Posts and a constructor for the Categories prop. It's an string array instead of List and I would like to keep it that way.
public class Post
{
public static List<Post> Posts = LoadPosts();
}
public Post()
{
ID = Guid.NewGuid().ToString();
Categories = new string[0]; //array, no List<string>
}
This is my razor markup
<ul class="categories">
#{var cl = Post.Posts.Where(p => p.IsPublished).Select(c => new List<string>(c.Categories));}
#foreach (var cat in cl.Distinct())
{
<li>#cat</li>
}
</ul>
This gives me as output
System.Collections.Generic.List`1[System.String]
I have done something wrong in my Linq, but I am not experienced enough (or awake) to see my mistake.
What you need is the SelectMany method:
Post.Posts
.Where(p => p.IsPublished) // IEnumerable<Post>
.SelectMany(c => c.Categories) // IEnumerable<string>
.Distinct()
It seems odd, but the real counterpart to the SQL select is not the IEnumerable.Select method, but the IEnumerable.SelectMany, because it can "flatten" the result of the selection, while Select makes a separate collection for each element, resulting in:
Post.Posts
.Where(p => p.IsPublished) // IEnumerable<Post>
.Select(c => c.Categories) // IEnumerable<IEnumerable<string>>
.Distinct() // does nothing, since all inner IEnumerable<string>
// objects are different
I would like to get those employees who have a phone number == "666666" using a LINQ query.
These are the class definitions:
public class Employees
{
public List<Phones> Phones{get;set}
}
public class Phones
{
public string Id{get;set;}
public string Number{get;set;}
}
This is my query (my doubt indicated as ???):
var employees= data.GetEmployees()
.Where(e=> e.Phones ???i need to navigate a level below phones ???)
.Select(e => new Employee()
{
Id=e.Id,
Name=e.Name
});
My problem is I don't know how to go a deeper level in this LINQ expression, because in e=>e... I have access to Phones as an IEnumerable but I would like to navigate to Phone's properties.
The easiest way to do this is to use nested LINQ queries. In this case you should look at the Any method.
var employees= data
.GetEmployees()
.Where(e => e.Phones.Any(p => p.Number == "666666"))
.Select(e => new Employee() {
Id = e.Id,
Name = e.Name
});
The parameter passed to the where method is merely a function that returns true or false for each given element, all methods (including LINQ ones (subject to accessing ref/out params etc)) can still be called within it:
var employees= data.GetEmployees()
.Where(e => e.Phones.Any(p => p.Number == "666666"))
.Select(e => new Employee()
{
Id=e.Id,
Name=e.Name
});
var employees= data.GetEmployees()
.Where(e=> e.Phones.Contains(x=>x.Number == "666666"))
.Select(e => new Employee()
{
Id=e.Id,
Name=e.Name
});
I am developing an MVC 3 application in C# and I would like to know how to list database entries, based on a condition. In my case, I only want to display invoices that have the status "Paid" or "Partly Paid".
So this is where I list them:
public ViewResult Index()
{
var invoices = db.Invoice.Include(c => c.Client);
return View(db.Invoice.ToList());
}
How I would I add the condition into this code?
Thanks,
Amy
Try this:
public ViewResult Index()
{
var invoices = db.Invoice.Include(c => c.Client).Where(i => i.Status !="Confirmed";
return View(invoices.ToList());
}