What is the logical difference between using Single and SingleOrDefault? [duplicate] - c#

This question already has answers here:
Should I use Single() or SingleOrDefault() if there is a chance that the element won't be found?
(9 answers)
Closed 5 years ago.
I am not sure where shall I use Single and where shall I use SingleOrDefault. I understood the definition for both.
Single:
It will always return one row.
If no row found I will get an exception.
If multiple rows found I will get an exception.
SingleOrDefault:
It will always return one row, if not found then default value is returned (What is the meaning of this DEFAULT VALUE").
If multiple rows then exception.
Question 1: What is the meaning of "It will return default value"
Question 2: When to use Single and when to use SingleOrDefault.
I have a delete function where I have below code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int resumeId)
{
var r = _context
.Resumes
.Where(c => c.ResumeId == resumeId).SingleOrDefault();
_context.Resumes.Remove(r);
_context.SaveChanges();
return RedirectToAction("ResumeCenter");
}
I just blindly put SingleOrDefault everywhere (where I ATMOST expect one value), Please tell me a real world scenario when I should use "Single" and where I should use "SingleOrDefault".

As you said -
Single() will raise an exception if no row found.
SingleOrDefault() will instead return the default value (null for reference types, 0 for ints, \0 for chars etc`).
Use Single() in one of two cases:
When not getting a row is something that should not happen, and if it does, it means something is wrong.
When you are dealing with value types (ints, chars, etc'), and the default value might be a valid value in your values system (for instance, if you are getting 0 for an int but can't tell if it's because you got no row back or it's a valid value.
Use SingleOrDefault() for any other case.
If the row is not found, you'll need to compare the value you get to it's default value.
For further reading, here is a link to Microsoft page on the default value expression.

It's almost (but not quite) a question of style. Which do you prefer?
Single:
try
{
var x = someEnumerable.Single();
}
catch (InvalidOperationException)
{
//Did not contain exactly one record
}
SingleOrDefault:
var y = someEnumerable.SingleOrDefault();
if (y == null)
{
//Did not contain exactly one record
}
The exception-based approach is a little more coding, but it is nice because exceptions can be allowed to bubble up. That being said, I usually use the XXXOrDefault variants to avoid stack unwind, which can be poor for performance. As a rule you should avoid throwing exceptions when behaviors are expected.
P.S. The "default" for any type can be obtained by using the keyword default(type). For integers it is zero, for dates it is MinValue, for reference types it is null, etc.
P.P.S. In your example I would use Single and allow an exception to be thrown if the row is missing or there is more than one. Otherwise you may end up passing null to the subsequent Remove method. While that would fail too, it'd fail a line later than it ought to, resulting in a deceptive stack trace and making troubleshooting a little trickier.
OTOH, with small changes, you could make either one work:
public ActionResult Delete(int resumeId)
{
var r = _context
.Resumes
.Where(c => c.ResumeId == resumeId).SingleOrDefault();
if (r == null)
{
return RedirectToAction("ErrorPage");
}
else
{
_context.Resumes.Remove(r);
_context.SaveChanges();
return RedirectToAction("ResumeCenter");
}
}
Or
public ActionResult Delete(int resumeId)
{
var r = _context
.Resumes
.Where(c => c.ResumeId == resumeId).Single(); //Error will bounce up to Application_Error or other global handler
_context.Resumes.Remove(r);
_context.SaveChanges();
return RedirectToAction("ResumeCenter");
}

as the function name suggest you when you say
list.single();
then that means
"I want the single record from the list" and hence you get the single
record (the 1st one)"
and when yo say
list.SingleOrDefault();
then that means
"I wan the single record and if the record dosen't exist the i would
like to have the default value of the object"
its your approch completely you can also go for
FirstOrDefault();
just like single or default

Single :
It returns a single specific element from a collection of elements if element match found. An exception is thrown, if none or more than one match found for that element in the collection.
SingleOrDefault:
It returns a single specific element from a collection of elements if element match found. An exception is thrown, if more than one match found for that element in the collection. A default value is returned, if no match is found for that element in the collection.

When you know that there has to be a value for some thing in the database, use Single() because you would want to get an exception if the "very expected value" in the database does not exist. Data like EmployeeName for a particular employee code.
Use SingleOrDefault() when you know employee is a temporary employee and his department may not show up in the main database. But if value for department exists, it should be only one value. He will not be working for multiple departments at once.
http://www.c-sharpcorner.com/blogs/singleordefault-vs-firstordefault-in-linq-query1
Single() - Atleast one value is expected in data store, and you would want it. You want to know if there is no value or multiple values. In that case, you get an exception and check.
SingleOrDefault() - Give one record with the default value if it does not exist. It does not matter whether on not anything is available for the record. But it should not be multiple records.

Related

Point variable to specific element of observable collection

I'd like to set a variable of type "ReturnOrderDetailLine" to be a specific "ReturnOrderDetailLine" within an "Observable Collection" of "ReturnOrderDetailLine"s.
Identifying the element I am interested in is done via searching for a barcode
public ObservableCollection<ReturnOrderDetailLine> ReturnLines
{
get => returnLines;
set
{
returnLines = value;
OnPropertyChanged(nameof(ReturnLines));
}
}
public ReturnOrderDetailLine SelectedLine { get; set; }
protected override void UpdateBarcodePickedOrReturnedQty(string barcodeText)
{
var returnDetailLine = (ReturnOrderDetailLine)ReturnLines.Where(s => s.Barcode.Equals(barcodeText));
SelectedLine = returnDetailLine;
OnPlusCommand();
}
I have tried using search methods like .select() or .where() but it seems the output of these functions are the same.
I've tried casting the result of .where() to the type I want but I receive a "Specified cast is not valid" error.
I've trawled googled for about an hour now and have gotten no insights.
Anyone have any ideas?
There are multiple methods that might satisfy your needs:
FirstOrDefault(): returns a first item of potentially multiple (or default if none exists).
First(): returns a first item of potentially multiple (or throw an exception if none exists).
SingleOrDefault(): assumes that there is a single item and returns it (or default if none exists). Multiple items are a violation of contract, an exception is thrown.
Single(): assumes that there is a single item and returns it (or throw an exception if none exists). Multiple items are a violation of contract, an exception is thrown.
Here's an example of using the FirstOrDefault() method in your scenario:
ReturnOrderDetailLine item = ReturnLines.FirstOrDefault(s => s.Barcode.Equals(barcodeText));
More about the differences between the FirstOrDefault(), First(), SingleOrDefault() and Single() can be found in this helpful stackoverflow answer.

How to check if a value exists in a list?

I'm relatively new to C# programming (programming as a whole, actually), but I've built an application to manage the application pools on a server that my team at work uses. It does everything it's supposed to fairly well, but the only issue I'm running into is in saving previously-used configurations to the app.config file so the user doesn't have to put them in manually every time. As it stands, I can save to and load from the file magnificently (along with all of the strings I need in each group).
The issue is that I want to do a cursory check to see if a Name string exists in the group before writing it. Example of the part of the app.config:
<appSettings>
<add Name="RowName" MachineName="MS-02348" AppSrvName="AppServer" WebSrvName="AppNet"/>
<add Name="RowName2" MachineName="MS-68186" AppSrvName="AppServer2" WebSrvName="AppNet2"/>
</appSettings>
So what I'm currently doing to load the values is I have a method that retrieves the appSettings/add nodes and throws them into a list, then sets the values to properties of an object. The reason I do this is so that I can have a drop-down that lists only the Name of an object, and then the rest of the information is all available for when I call the method on the selected item.
Anyway, what I'm running into now is that I want to make sure that if the Name already exists in the app.config, I prompt the user to write another name instead of saving it to the database. Having two child nodes with the same "Name" value would wreak havoc on my logic.
I tried a foreach to cycle through the objects in the list, but without knowing how many objects there could be I didn't know of an easy way of really saying it does or does not exist. I've also tried targeting the childnode based on the values listed in the node, but it seems to fail there too. I'm guessing that part is syntax, but it seems to match up with how the method list defines it.
Any thoughts?
if (list.Any())
{
// found something!
}
else
{
// found nothing
}
I always use Any() simply because it's the most performant. List.Count() goes through each item and counts them, but you don't care about the number of items -- you only care if there's an item at all. Any() will enumerate through the list and stop if it finds an item. So, in the extreme case, in a list of a million items Count() will enumerate every single one and return while Any() will enumerate one and return.
Plus, it returns a bool, which is handy for more concise code. :)
As an added bonus, you can call Any() looking for specific things. So, in a list of people I can look to see if there are any people older than 21 in it:
if (list.Any(person => person.Age > 21))
{
// ...
}
Edit: Formatting.
maybe something like this
var list = new List<AppSettings>();
var item = list.FirstOrDefault(x => x.Name == NameEnteredByUser);
if (item == null)
{
//there is no such item
}
else
{
//notify the user
}
or the Any extension method:
var list = new List<AppSettings>();
if (list.Any(x => x.Name == NameEnteredByUser))
{
//name exists
}
else
{
//no such name used before
}
As a sidenote, have a unique field configured in your database so that when your programming logic fails you wont enter a record. corrupt data state in db is bad.
neo112 is correct in his logic, but I am unsure if the main problem you have is performance related, since you mention you dont know if it may get too long.
First, you could also do the following;
int count = list.Count(a => a.Name == NameEnteredByUser);
if(count > 0)
{
// exists
}
I believe .Count() is faster than .First() (anecdotal evidence only) and personally think it's a bit cleaner.
Also, another thing you could try to do is to sort your list by name when adding to the appSettings node. Then, you should instantiate a SortedList instead of just List, then that would also (possitively) affect performance. But, I am unsure if sorting is an option for you.

Benefits between .ToList().First() verse .Single for IQueryable in c#

So I am running a linq query on a NOSQL database that should return only a single object if one exists with that Id or nothing if nothing exists, but it is possible there are two objects with the same id in the database (if someone else messed up.) Currently I have it implemented as follows:
(from c in [IQueryableThing] where c.Id.Equals(id)).ToList().First()
I have also considered the alternative
(from c in [IQueryableThing] where c.Id.Equals(id)).Single()
I assume .Single() is faster but I am concerned that neither of these handles the case that there is no object with the correct id in the database. I don't care if there is more than one returned. I only want one of them. Eventually I will implement something to return the most recently modified.
Basically my question is what is the best way to solve this problem of converting a queryable to a single instance in a way that handles the cases where there is no object with the correct id and there is more than one object with the correct id.
It sounds like you just want to call FirstOrDefault(), which does exactly what the name implies.
Default means null.
You should not call ToList(); that will needlessly download all of the results from the database.
Using IQueryable.Single is more efficient:
Calling ToList enumerates the entire result set and stores each item in an single, contiguous array in memory. The First then just takes the first item from the array.
Calling IQueryable.Single evaluates only the first item in the list, and if no items are returned, throws an exception. It then checks to see if there are any more items in the result set, and throws an exception if there are any.
If you'd like to handle the case where no items exist in the set which match your criteria, but don't care if there are more than one, I'd strongly recommend using FirstOrDefault instead:
var result = (from c in [IQueryableThing] where c.Id.Equals(id)).FirstOrDefault();
if (result == null)
{
// no items found
}
This will translate to a TOP 1 in SQL, and simply return the first item in the result set, or if the result set is empty, it will simply return null (or the default value if you're dealing with structs).
The .ToList() shouldn't make a difference, it will just enumerate the queryable into an in-memory list. For your situation, you have a number of options. The two you've shown behave very differently:
.First() - This will return the first element in the enumeration, or throw an exception if there are none.
.Single() - This will return the only element in the enumeration, or throw an exception if there are none or if there are more than one.
.FirstOrDefault() - This will return the first element in the enumeration, or a default value (which is null for reference types) if there are none.
.SingleOrDefault() - This will return the only element in the enumeration, or a default value (which is null for reference types) if there are none, or throw an exception if there are more than one.
It sounds like you want to use .FirstOrDefault(). Check if the result is null. If it is, there were no matching elements. If it isn't, you have the first matching element.
I believe you are looking for Enumerable.FirstOrDefault
Returns the first element of a sequence, or a default value if the
sequence contains no elements.
You should use .FirstOrDefault(c => c.ID.Equals(id));
It will return default if nothing is found (default is null for classes) or the first one it finds.
In case you are sure that ONE and only ONE item exists and you will want to use Single()
If case you are not sure how many items will be returned used First() Or FirstOrDefault().
The difference is that Single() will throw an exception if more than one item exists. Very usefull if you want to trap insertion errors etc on a database without unique constraints.

LINQ Query Issue, Sequence contains no elements

I'm trying to update a single record in a table, but when I run .Firstordefault(), I get the error: "Object reference not set to an instance of an object.", and if use it with .First(), I get "Sequence contains no elements".
Using it another place, its working fine, but this time its causing errors.
Here's the code:
public class AllownceDetails
{
public int ta_id{get;set;}
public int tvrid{get;set;}
public DateTime ofDate{get;set;}
public string status{get;set;}
public string userid {get;set;}
}
//Update Method
public void Update(AllownceDetails Allowncedtl)
{
var ta = (from a in ce.tbl_tvrallownce
where a.tvrid == Allowncedtl.tvrid
//error: Sequence contains no elements
select a).SingleOrDefault();
ta.status = Allowncedtl.status;
//error:Object reference not set to an instance of an object
ce.SaveChanges();
}
The query must not be returning any data. Run a profiler on the SQL database to see the physical query being executed and try to execute it manually against the database to see what the data looks like. You probably have to adjust the query (or the data) to get the results you're looking for.
"Sequence contains no elements" is basically LINQ's way of telling you that you're trying to reference an element from a list that doesn't have anything. So calls to things like .First() or .Single() can't find anything, hence the error.
When you change the calls to something like .FirstOrDefault() or .SingleOrDefault() then it will go with "default" value for that type, and for reference types the default is null. So if you set something to null and then try to call a method on it, you'll get object reference not set to an instance of an object.
The Single method throws this exception when there are no elements in list(query) or there are multiple elements.
The SingleOrDefault method throws an exception when there are multiple elements in the list. Returns null when there are no elements.
The FirstOrDefault method return the first item in the list or null. There are no exceptions.
Use it and the check the reference for null
if (ta != null )
{
ta.status = Allowncedtl.status;
ce.SaveChanges()
}
The source will always be an object, so no worries about it in your case.
All that means is that your query isn't matching anything. Presumably Allowncedtl.tvrid is an ID which doesn't match anything in the database. You shouldn't assume that SingleOrDefault will return a non-null value. Only use SingleOrDefault when you're expecting that there may be no values - and cope with that. If a failure to find a value indicates a bug, you should use Single (or perhaps First) instead.
We can't tell anything about what the underlying cause of your error is - you should log which ID you were looking for, work out why you were looking for that, and then check it in the database.

How check null value for a proxy

I have a generic methode for load the entity. I need to check result value for null value.
public TEntity LoadById(long id)
{
TEntity result = SessionInstance.Load<TEntity>(id);
if (result != null) //This condition is always true
if (result.Id == 0 ) //Throws ObjectNotFoundException
throw new Exception("Ex Text");
return result;
}
But my condition ( if (result != null) ) is always true and next line result.Propagate() is throw ObjectNotFoundException exception by this message : No row with the given identifier exists[RCISP.Domain.Entities.Person#1000]
Because result entity is a proxy.
How can I check a condition for null value in a proxy?
Use NHibernate's ISession.Get instead of ISession.Load. Load throws an exception if the requested item does not exist, but it might also return a proxy that is later used to load the object from the database - and will only then throw if the item does not exist. That's what is happening to you.
Get on the other side returns null if the item does not exist in database. Exactly what you want.
More on that topic here.
Daniel's initial answer is correct. According to Ayende's blog, Load should only be used when you know that the item exists in the database.
Load will never return null. It will always return an entity or throw an exception. Because that is the contract that we have we it, it is permissible for Load to not hit the database when you call it, it is free to return a proxy instead.
Why is this useful? Well, if you know that the value exist in the database, and you don’t want to pay the extra select to have that, but you want to get that value so we can add that reference to an object, you can use Load to do so
In your example, the ObjectNotFoundException can only occur when the item does not exist in the database. If you can't guarantee that the item is present, you need to use Get not Load.

Categories

Resources