method group filter null values - c#

I have the following code:
IEnumerable<DestinationResult> destinations =
_repository.GetDestinationData();
IEnumerable<Destination> finalDestinations =
destinations.Select(GetAdditionalDestinationInfo);
private Destination GetAdditionalDestinationInfo(DestinationResult d){ /* CODE */}
How can I still use the method group call (Select(GetAdditionalDestinationInfo)) and filter out the null values that might be returned from GetAdditionalDestinationInfo (without having to call the method again to check for null in a where clause).
Something like:
IEnumerable<Destination> finalDestinations =
destinations.Select(GetAdditionalDestinationInfo != null)

Select maps input records to output records, one by one - there's no opportunity for filtering. Instead, you want to add another Where:
IEnumerable<Destination> finalDestinations =
destinations
.Select(GetAdditionalDestinationInfo)
.Where(i => i != null);

Related

Apply filters only if parameters has values in linq

Iam using LINQ to retrieve records from the database. Everything is working fine, except I need to apply the different filters in a single query. If the parameters are not Null and greater than zero then apply filters. Otherwise, if they are Null or zero, then don't apply the filters.
Below is the example:
bankId(int) and accountNumber(string) are my two parameters.
if bankId > 0 then get the records matching the bankId, if accountnumber is passed then get the records matching the accountnumber.
If both are passed pull all the records matching with bankid and accountnumber.
If both are not passed then return all records without applying filter.
Currently I am able to achieve it like this,
Without applying any filter I am fetching all records and then if bankId is passed applying filter on the above result and if accountnumber is passed again applying filter on the above result.
But the issue here is this approach is leading to multiple if conditions which I don't want.
Is there any best and simple way to apply these filters in single query and get the result?
Please suggest, Thanks in advance.
build your statement this way
var items = context.accounts.AsQueryable();
if (bankId > 0)
{
items = items.Where(x => x.bankId == bankId);
}
if (!string.IsNullOrEmpty(accountnumber))
{
items = items.Where(x => x.accountnumber == accountnumber);
}
var result = items.ToList(); // query db / materialize here!
You can define a function and filter by this function using LINQ operation. C# supports functional programming in linq operations.
Here below I defined a function(filterAccounts) that returns boolean if satisfies the requirements.
After that I sent this function as a parameter to Linq Where method. Where method call's filterAccounts method for each element and if returns true, than yields it and finally returns all elements that returns true.
I hope it helps.
List items = getItemsAslist();
Func<item, bool> filterAccounts = (i) =>
{
return (bankId > 0 ? i.bankId == bankId : true)
&& (!string.IsNullOrEmpty(accountnumber) ? accountNumber == i.accountNumber : true)
};
items = items.Where(filterAccounts);

LINQ Query, Return Max Value with Where Clause

I'm working on an API; how can I set my linq query up to return the max value with a where condition?
See the example code below; I can return the max value of the field I want, but I need to filter it where another column value equals something.
var lot = db.ShrinkLotData.Where(x => x.SupplierMfgLot.ToLower() == label.SupplierMfgLot.ToLower() && x.CatPattern.ToLower() == label.CatPattern.ToLower())
.SingleOrDefaultAsync();
if (lot.Result == null)
{
var lots = db.ShrinkLotData.Where(x => x.CatPattern.ToLower() == label.CatPattern.ToLower());
int internallot = db.ShrinkLotData.Max(x => x.InternalLotNum).Value;
return Ok(lot);
}
return Ok(lot);
}
for the internallot, I want to return the highest value using similar syntax as the lots syntax.. (Where the catpattern equals a specific value)
What am I overlooking?
Thanks!
If I understand correctly, you basically need to use Where and Max together, so that you can select max value with a where condition.
db.ShrinkLotData.Where(x => x.CatPattern.ToLower() == label.CatPattern.ToLower()).Max(x => x.InternalLotNum).Value;
More Info : Composability of Queries:
..., you compose them in method syntax by
chaining the method calls together. This is what the compiler does
behind the scenes when you write queries by using query syntax. And
because a query variable does not store the results of the query, you
can modify it or use it as the basis for a new query at any time, even
after it has been executed.

ASP.NET MVC C# Select and Where Statements

I'm having trouble understanding .Select and .Where statements. What I want to do is select a specific column with "where" criteria based on another column.
For example, what I have is this:
var engineers = db.engineers;
var managers = db.ManagersToEngineers;
List<ManagerToEngineer> matchedManager = null;
Engineer matchedEngineer = null;
if (this.User.Identity.IsAuthenticated)
{
var userEmail = this.User.Identity.Name;
matchedEngineer = engineers.Where(x => x.email == userEmail).FirstOrDefault();
matchedManager = managers.Select(x => x.ManagerId).Where(x => x.EngineerId == matchedEngineer.PersonId).ToList();
}
if (matchedEngineer != null)
{
ViewBag.EngineerId = new SelectList(new List<Engineer> { matchedEngineer }, "PersonId", "FullName");
ViewBag.ManagerId = new SelectList(matchedManager, "PersonId", "FullName");
}
What I'm trying to do above is select from a table that matches Managers to Engineers and select a list of managers based on the engineer's id. This isn't working and when I go like:
matchedManager = managers.Where(x => x.EngineerId == matchedEngineer.PersonId).ToList();
I don't get any errors but I'm not selecting the right column. In fact the moment I'm not sure what I'm selecting. Plus I get the error:
Non-static method requires a target.
if you want to to select the manager, then you need to use FirstOrDefault() as you used one line above, but if it is expected to have multiple managers returned, then you will need List<Manager>, try like:
Update:
so matchedManager is already List<T>, in the case it should be like:
matchedManager = managers.Where(x => x.EngineerId == matchedEngineer.PersonId).ToList();
when you put Select(x=>x.ManagerId) after the Where() now it will return Collection of int not Collection of that type, and as Where() is self descriptive, it filters the collection as in sql, and Select() projects the collection on the column you specify:
List<int> managerIds = managers.Where(x => x.EngineerId == matchedEngineer.PersonId)
.Select(x=>x.ManagerId).ToList();
The easiest way to remember what the methods do is to remember that this is being translated to SQL.
A .Where() method will filter the rows returned.
A .Select() method will filter the columns returned.
However, there are a few ways to do that with the way you should have your objects set up.
First, you could get the Engineer, and access its Managers:
var engineer = context.Engineers.Find(engineerId);
return engineer.Managers;
However, that will first pull the Engineer out of the database, and then go back for all of the Managers. The other way would be to go directly through the Managers.
return context.Managers.Where(manager => manager.EngineerId == engineerId).ToList();
Although, by the look of the code in your question, you may have a cross-reference table (many to many relationship) between Managers and Engineers. In that case, my second example probably wouldn't work. In that case, I would use the first example.
You want to filter data by matching person Id and then selecting manager Id, you need to do following:
matchedManager = managers.Where(x => x.EngineerId == matchedEngineer.PersonId).Select(x => x.ManagerId).ToList();
In your case, you are selecting the ManagerId first and so you have list of ints, instead of managers from which you can filter data
Update:
You also need to check matchedEngineer is not null before retrieving the associated manager. This might be cause of your error
You use "Select" lambda expression to get the field you want, you use "where" to filter results

Check if query to DB is empty

The action method in the controller receive a value, like a couple of letters. The code checks if the table contains any of this letters. I'm using this code for that task:
var result = db.People.Where(b => b.Name.ToUpper().Contains(filter.ToUpper()));
But how can I check if the result variable is empty or null, when there are not any matching letters? I tested this, but it's not working!
If(result == ""){
// Do something
}
I would like to use Viewbag to send a message that there was no match or perhaps do this check in the View. I'm using this with some AJAX and Partial Views and it's working perfect, but I just want show a message if there are not any matches. What is the best way to check if the result value is empty or null?
The simplest way would be by using !result.Any():
var result = db.People.Where(b => b.Name.ToUpper().Contains(filter.ToUpper()));
If(!result.Any()){
// Do something
}
From MSDN on IEnumerable:
Any()
Determines whether a sequence contains any elements.
Fits exactly what you need.
Try this, Using FirstOrDefault it will give you the first record from the result, else if no result is yielded from the query it returns default value that is null,
var result = db.People.Where(b => b.Name.ToUpper().Contains(filter.ToUpper())).FirstOrDefault();
If(result == null){
// Do something
}
Or if you want to use this result, to manipulate something in your code then you can use the ToList(). It will return you list of values and if the query didnt yield anything then the list count will be 0.
var result = db.People.Where(b => b.Name.ToUpper().Contains(filter.ToUpper())).ToList();
If(result.Count == 0){
// Do something
}
Your code is not working because the code is returning an object not a string if you want to return a string then you have to use the "Select" clause to select a specific field and if you want to check in the same code then modify :
var result = db.People.Where(b => b.Name.ToUpper().Contains(filter.ToUpper())).ToList();
if(result != null && result.Count > 0)
it will work for you.
For IEnumerable we can use Any(), your code will can be written as
if(!db.People.Where(b => b.Name.ToUpper().Contains(filter.ToUpper())).Any() {
// do some thing
}

Question about multiple criteria List(T).Where

now I can not get the correct information
List<HeaderHelper> h = pr.Actual_View();
foreach (TemplateHeader t in pr.TemplateView())
{
var v= h.Where(z => z.Country == t.Pais
&& z.dia == t.diaTotal
&& z.Segment == t.Segmento).FirstOrDefault();
}
The
pr.Actual_View()
is a class method for a list containing the following fields:
Country (string)
dia (int)
Segment (string)
The
pr.TemplateView()
is a class method for list containing the same fields and same datatype
the list t may contain more information than the list h, so I need to filter the list h with several criteria, but when I run the code does not correctly filter the list, returning a null.
If v is null, that suggests that none of the values in t matched your Where clause, so FirstOrDefault returned the default value of TemplateHeader, which is null.
Without more information or sample data we've got absolutely no way of knowing why none of the values in t matched, but that's what the null value of v indicates.

Categories