Since .NET Core 3 we can no longer use GroupBy without calling AsEnumerable or ToList first.
The problem with calling AsEnumerable is that it makes the oData queries case sensitive. This filter with 'aaaa' does not find 'A' for instance:
https://localhost/myweb.api/api/mymethod?$filter=contains(Name,%20%27aaaa%27)
How can I make this case insensitive again?
this is not production code, just an example:
public IQueryable<Dto> GetDto(
{
return (from a in _context.Names
select new Dto
{
Name = a.Name
})
.AsEnumerable() // this is needed for the group by to work
.GroupBy(x => new { x.Name })
.Select(x => new Dto
{
Name = x.Key.Name
})
.AsQueryable();
}
You can try with same cases by making .tolower() or .toUpper() and apply where condition to filter the records:
var searchText = "A";
return (from a in _context.Names
select new Dto
{
Name = a.Name
})
.Where(x=>x.Name.ToLower().Contains(searchText.ToLower()))
.AsEnumerable()
.GroupBy(x => new { x.Name })
.Select(x => new Dto
{
Name = x.Key.Name
})
.AsQueryable();
Related
I am trying to write a subquery in linq here is my SQL script
Select id, name from employee where id in (select dictinct id in salaryEmp)
I have tried several combination but not getting the desired output. I will appreciate any help in this regards
This should do it:
db.employee
.Where(x => salaryEmp.Select(x => x.id).Distinct().Contains(x.id))
.Select(x => new { x.id, x.name });
Or better you can do:
var idList = salaryEmp.Select(x => x.id).Distinct().ToList();
var result = db.employee
.Where(x => idList.Contains(x.id))
.Select(x => new { x.id, x.name });
You didn't say how your context looks like, but it will be something like that:
from e in ctx.employee
where
(from s in ctx.salaryEmp
select s.Id).Distinct().Contains(e.id)
select new { e.Id, e.Name }
or with sub query as method-based query:
from e in ctx.employee
where ctx.salaryEmp.Select(s => s.Id).Distinct().Contains(e.id)
select new { e.Id, e.Name }
How can I add an orderby after the select?
//what I have now
string country_list = string.Join(":", ctx.Countries.Select(a => a.CountryName).ToArray());
return country_list;
//what I want to do, but the orderby doesnt see the projections
string country_list = string.Join(":", ctx.Countries.Select(a => a.CountryName).OrderBy(b => b.StateId).ToArray());
return country_list;
its the projection with b that isnt working
You have to call OrderBy before Select, because after projection the column you're trying to order by is no longer available:
string country_list = string.Join(":", ctx.Countries.OrderBy(b => b.StateId).Select(a => a.CountryName).ToArray());
ctx.Countries.Select(a => new { a.CountryName, a.StateId })
.OrderBy(b => b.StateId)
.ToArray()
Is there any possibility to get only one column from .Where statement? For example - ID.
List<testB> test = db.testB.Where(x => x.UserID == userId).ToList();
Here I get all entites testB.
And I just want to return List<int> with testB.ID instead of List<testB>. How can I do this?
db.testB.Where(x => x.UserID == userId).Select(x => x.ID).ToList();
should return a List<int>
Try using .select like this
var test = db.testB.Where(x => x.UserID == userId)
.Select(a => new {
column = a.column
}).ToList();
this creates an anonymous type class of only on attribute. Try it out.
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
});
Here is my scenario: We would like to have a page listing donors, depending on the user viewing the page we would like to group by the donor's giving level, or just their sort name. The twist that is throwing me is that we would like to group the Anonomous Donors and give a count based on the grouping.
In my controller I have
[HttpGet]
public ActionResult Society(string id)
{
var society = _db.ONLINEDR_DONOR_LIST
.Include("ONLINEDR_DONORS")
.Single(s => s.DONOR_LIST_ID == id);
var donors = _db.ONLINEDR_DONORS
.Where(d => d.DONOR_LIST_ID == id)
.OrderBy(d => d.SUBGROUP_SORT)
.ThenBy(d => d.SORT_NAME)
.ToList();
if (User.Identity.Name == "public")
{
//First off, check to make sure the list is viewable.
if (society.PUBLIC_IND == "N")
RedirectToAction("Index", "Home");
donors = _db.ONLINEDR_DONORS
.Where(d => d.DONOR_LIST_ID == id)
.OrderBy(d => d.SORT_NAME)
.ToList();
}
var viewModel = new SocietyDetailViewModel()
{
Society = society,
Donors = donors
};
return View(viewModel);
}
I would like to have something like
donors = _db.ONLINEDR_DONORS
.Where(d => d.DONOR_LIST_ID == id)
.GroupBy(d => d.SORT_NAME)
.ToList();
Which I can pass to my view, and then somehow show in the view
<% if (Model.donor.GroupedByItemCount > 1) { %>
<%: Model.donor.GroupedByItemCount %>
<% } %
(I am still new to asp.net MVC and LINQ so any helpful references to explain what I am doing wrong would be appreciated as well).
Thanks so much.
In the declaration of the donors variable, the compiler can determine the type of donors to be List<Donor>
In the assignment within the desired code, donors must be a List<IGrouping<string, Donor>>
donors cannot simultaneously be both types.
Suppose you have this query:
List<IGrouping<string, Donor>> donors = _db.ONLINEDR_DONORS
.Where(d => d.DONOR_LIST_ID == id)
.GroupBy(d => d.SORT_NAME)
.ToList();
This query is local and gives you the keys:
donors.Select(g => g.Key)
This query is mixed mode. A query is sent to the database for each item in the list to fetch its count. This is a potential performance problem.
donors.Select(g => g.Count())
This behavior is due to the difference between LinqToObjects groupby and sql's groupby.
In sql's groupby, you get the key and the aggregates - no elemeents.
In LinqToObjects, you get the key and the elements of the group - and can compute the aggregates from the elements.
Suppose you have this query:
List<IGrouping<string, Donor>> donors = _db.ONLINEDR_DONORS
.Where(d => d.DONOR_LIST_ID == id)
.ToList()
.GroupBy(d => d.SORT_NAME)
.ToList();
In the above query, the records are first hydrated, and then grouped locally. All queries on the result are local.
This query shapes the result data from IGrouping<string, Donor> to GroupShape. GroupShape is some class you make up that has SortName and Count properties.
donors.Select(g => new GroupShape()
{
SortName = g.Key,
Count = g.Count()
});
Suppose you have this query:
List<GroupShape> donors = _db.ONLINEDR_DONORS
.Where(d => d.DONOR_LIST_ID == id)
.GroupBy(d => d.SORT_NAME)
.Select(g => new {SortName = g.Key, Count = g.Count()})
.ToList()
.Select(x => new GroupShape()
{
SortName = x.SortName,
Count = x.Count
}).ToList();
Here, the grouping and counting are done in the database. Each row is first hydrated into an anonymous instance and then copied into an instance of GroupShape (a class you make up).