Find record based on value from the table - c#

This is my code to find string in my UserTable.
var PhoneExists = _db.UserTable.Where(u => u.PhoneNumber == Input.PhoneNumber);
and this is my if code:
if (PhoneExists != null)
{
ErrorAlert("number found.");
return Page();
}
but every time the if condition is true.

It returns true as PhoneExists is not null, but it returns with IQueryable value.
You need to materialize the query to return the result queried from the database.
You may look for .Any() to find whether there is any record with the respective PhoneNumber existed.
bool PhoneExists = _db.UserTable.Any(u => u.PhoneNumber == Input.PhoneNumber);
if (PhoneExists)
{
...
}

Where will always return a non-null enumerable, and it's empty if there are no matches. You have to check its contents. If you expect the phone numbers to be unique, you could use FirstOrDefault or SingleOrDefault to return either a string, or null. The latter will, however, throw if there is more than one match.

You can use Contains here.
Sample code:
var PhoneExists = _db.UserTable.Where(u => u.PhoneNumber.Contains(Input.PhoneNumber)).FirstOrDefault();
In your if code:
if (PhoneExists != null && PhoneExist.Count()== 0)
{
ErrorAlert("number found.");
return Page();
}

You can use Exists instead of Where like this :
if (_db.UserTable.Exists(u => u.PhoneNumber == Input.PhoneNumber))
{
//Do Something
}
About exist checkout https://learn.microsoft.com/tr-tr/dotnet/api/system.collections.generic.list-1.exists?view=net-6.0

You can use FirstOrDefault()
var PhoneExists = _db.UserTable.Where(u => u.PhoneNumber == Input.PhoneNumber).FirstOrDefault();

Related

How to use linq to return a boolean

I have a foreach loop where I'm iterating through a list to make sure every item is valid and want to return a boolean.
Here's my foreach code:
bool isValid = true;
foreach (var req in requestList)
{
if (!req.ChannelId.HasValue || !req.PayoutAmountInCents.HasValue)
{
isValid = false;
PayoutFDEvents.LogInvalidPayoutRequest(this.BuildPayoutFDDocument(req), "missing channelId or patronage amount");
}
}
and here's my attempt to convert it to a linq statement:
var isValid = requestList
.Select(r =>
{
if (!r.ChannelId.HasValue || !r.PayoutAmountInCents.HasValue)
{
PayoutFDEvents.LogInvalidPayoutRequest(this.BuildPayoutFDDocument(r), "missing channelId or patronage amount");
return false;
}
return true;
});
However, looks like my implementation returns a list of bools instead. Is there a way I can return an overall bool?
This could be converted to a simple expression like this:
var isValid = requestList.All(r => r.ChannelId.HasValue && r.PayoutAmountInCents.HasValue)
I would suggest you don't log something in the middle of your expression - this is just smelly and won't work very well once you convert to using All()
You can also try this:
var invalids = requestList.Where(r => !(r.ChannelId.HasValue && r.PayoutAmountInCents.HasValue)).ToList();
invalids.ForEach(r => PayoutFDEvents.LogInvalidPayoutRequest(BuildPayoutFDDocument(r), "msg"));
bool isValid = invalids.Any();
I think your logic is too complex to be done in a one line statement.
One option would be to use:
var isValid = requestList
.Select(r =>
{
var valid =r.ChannelId.HasValue && r.PayoutAmountInCents.HasValue;
if (!valid)
{
PayoutFDEvents.LogInvalidPayoutRequest(
this.BuildPayoutFDDocument(req), "missing channelId or patronage amount");
}
return valid;
})
.DefaultIfEmpty(true)
.Min();
Because false is "less" than true, this will return false if any of the individual entries meet the condition (i.e. are null).
The DefaultIfEmpty bit is to handle the scenario where requestList is empty - in which case isValid will be set to true.
In all honesty though, since you are performing the logging inside your existing loop I would keep your existing code. It is simple, clear, and easy to read and understand.

Avoid NullReferenceException in LINQ Expression on Datatable column

I am stuck with null values in my Datatable "articles". Using LINQ to get a list of articles works for column ArticleId but with column "ArticleVariations" the null values are killing me.
var result = this.articles.AsEnumerable().Where(r =>r.Field<String>("ArticleId").Equals(artNo)); // works. no nulls there ;)
var result = this.articles.AsEnumerable().Where(r =>r.Field<String>("ArticleVariations").Equals(artNo)); // stuck with nulls here
If the column contains nulls, I get an NullReferenceException, Can I avoid this somehow and is it possible to merge both expressions?
You can use null-conditional and null-coalescing operators:
var result = this.articles.AsEnumerable()
.Where(r =>r.Field<String>("ArticleVariations")?.Equals(artNo) ?? false);
The problem obviously occurs because r.Field<String>("ArticleVariations") retuns null. Thus you have to check for null before calling Equals on it.
For that you can call multiple statements within a LINQ-expression:
var result = this.articles.AsEnumerable().Where(r => {
var res = r.Field<String>("ArticleVariations");
if (res != null) return res.Equals(artNo);
else return false;
});
If the field can be null then just reverse your test:
var result = this.articles.AsEnumerable().Where(r => artNo.Equals(r.Field<String>("ArticleVariations")));
Then all you need to do is check that artNo is not null before making the call:
List<Type> result;
if (string.IsNullOrWhiteSpace(artNo))
{
result = new List<Type>();
}
else
{
result = this.articles.... as before
}
Where just takes a function which returns a bool to determine if it should filter an item out of a collection. You can write it with a multi-statement body just like any other function to make nulls easier to deal with. Something like this should be a good starting point:
.Where(r => {
string articleVariations = r.Field<string>("ArticleVariations");
return articleVariations != null && articleVariations.Equals(artNo);
});
IF you want to combine those checks somehow to build a list where one or the other of the given fields matches your artNo, you can just add it to the function body.
If the column contains nulls, I get an NullReferenceException, Can I avoid this somehow
Avoid using instance Equals methods where possible. Use the respective operators or static Equals methods because they handle correctly nulls for you.
In your concrete case, the easiest way is to replace Equals with ==:
var result = this.articles.AsEnumerable()
.Where(r => r.Field<string>("ArticleId") == artNo);
var result = this.articles.AsEnumerable()
.Where(r => r.Field<string>("ArticleVariations") == artNo);
and is it possible to merge both expressions?
It depends on what do you mean by "merging" them. If you mean matching article or variation by the passed artNo, then you can use something like this
var result = this.articles.AsEnumerable()
.Where(r => r.Field<string>("ArticleId") == artNo
|| r => r.Field<string>("ArticleVariations") == artNo);

List<string> get item that starts with Name= using LINQ

How can i retrieve from a List<string> the item(value) that starts with Name=
If the list contains the values:
Name=Jhon Smith
Age=20
Location=CityName
I want to get the value Jhon Smith.
I do know how to traditionally loop through the list using foreach and have a condition if value starts with Name= ... but I'm not that good with LINQ.
This will throw an exception if there is no such element in the collection.
You can use FirstOrDefault and check if you get null or an element to check
whether there was a match or not.
list.First(x => x.StartsWith("Name=")).Substring(5)
This won't throw an exception:
var prefix = "Name=";
var elem = list.FirstOrDefault(item => item.StartsWith(prefix));
if (elem != null) {
return elem.Substring(prefix.Length)
} else {
return null;
}
Use Single or SingleOrDefault like this:
var result = list.Single(s => s.StartsWith("Name=")).Substring(5);
or
string result = string.Empty;
var element = list.SingleOrDefault(s => s.StartsWith("Name="));
if (element == null)
{
//"Name=" not present, throw an exception
}
result = element.Substring(5);
or similarly with First, or FirstOrDefault depending on what you exactly want.
There was another interesting answer by the user canon, but was deleted (I don't know why):
var result = list
.Where(x => x.StartsWith("Name="))
.Select(x => x.Substring(5))
.FirstOrDefault();
Its advantage is that it won't throw regardless of the input data.
String match = list.FirstOrDefault( str => str.IndexOf("Name=", StringComparison.InvariantCulture) > -1 );
return match.Substring("Name=".Length);

First match in a collection

I want to convert this code to a linq solution. What it does it looks into a collection of customers and see if at least one of the has a middle name. This code works fine, I'm just trying to learn linq, so looking for an alternative solution.:
//Customers - List<Customer>
private bool checkMiddleName()
{
foreach (Customer i in Customers)
{
if (i.HasMiddleName == true)
{
return true;
}
}
return false;
}
I tried to write something like: (Customers.Foreach(x=>x.HasMiddleName==true)...
but looks line it's not the method I'm looking for.
If you just want to know if theres at least one, you can use Enumerable.Any:
bool atLeastOneCustomerWithMiddleName = Customers.Any(c => c.HasMiddleName);
If you want to know the first matching customer, you can use Enumerable.First or Enumerable.FirstOrDefault to find the first customer with MiddleName==true:
var customer = Customers.FirstOrDefault(c => c.HasMiddleName);
if(customer != null)
{
// there is at least one customer with HasMiddleName == true
}
First throws an InvalidOperationException if the source sequence is empty, whereas FirstOrDefault returns null if there's no match.
var result = Customers.Where(x=>x.HasMiddleName == true).FirstOrDefault();
Based on this:
What it does it looks into a collection of customers and see if at least one of the has a middle name.
Try
return Customers.Where(x => x.HasMiddleName).Any();
This query return true if at least one custmer has the property HasMiddleName = true
You may use the following to achieve what you need:
Customers.Where(cust=> cust.HasMiddleName).Count > 0
So , if Count is more than zero means you have some customers who have Middle name.
Or for better performance you may say:
bool customerWithMiddleName;
foreach(Customer cust in Customers)
{
if(cust.HasMiddleName)
{
customerWithMiddleName = true;
break;
}
}

Null check ObservableCollection before querying it

Is this code good enough:
if (MyCollection.Where(p => p.SomeID == idstring).Any())
{
selectedval = MyCollection.Where(p => p.SomeID == idstring).FirstOrDefault().MyField;
}
My doubt is about the fact that I make the same query twice: first for null check and then to actually get data.
Maybe there is a better way to do this type of things?
Yes.
var item = MyCollection.FirstOrDefault(p => p.SomeID == idstring);
if (item != null)
selectval = item.MyField;
This avoids double querying the collection, which will certainly make a difference in big collections or if your collection performs a DB query.
There is. You can use the FirstOrDefault method which takes a predicate and returns null if the item is not found.
var result = MyCollection.FirstOrDefault(p => p.SomeID == idstring);
if( result != null )
{
// item was found
}

Categories

Resources