I am new to Linq and C#, I've spent a very long time trying to solve this very simple problem.
I have the following code:
var currcard = from c in db.CreditCards where c.Id == cid select c;
Where db is a database context and credit cards is a table in that database.
This has the possible result of returning several records, which I then iterate through using a foreach. When there are records to be returned, everything works beautifully.
Sometimes, however, no records are returned, and I get the 'Sequence contains no elements' error. I don't want to use FirstOrDefault or SingleOrDefault, because I want ALL the records if they are returned. However, I cannot for the life of me figure out what equivalent to these functions I would use when I need null if NO records are returned.
I would not be surprised if the solution weren't simple. Sometimes c# seems overly complex.
Edit: In the end I discovered that the error was being thrown by the SaveChanges method on the context, not the assigning statement or iteration block. Using the Any keyword led me in the end to discovering my problem, so even though it turned out to be a separate issue, I've marked that answer as correct. But thanks to everyone for your assistance.
You can iterate over it without issues:
foreach (var r in currcard) // won't throw
Likewise, you can check beforehand if there are any items in the list:
if (currcard.Any()) // won't throw
If the sequence is empty and you iterate over it, nothing should happen, which is the semantic you usually want (and what you're looking for as well). What exactly is the iteration code you're using? A foreach shouldn't have any problems with an empty sequence.
The Any() method will be true if the sequence contains elements. When working with databases it's usually a lot more efficient that using Count() > 0
var currcard = from c in CreditCards where c.Id == cid select c;
if (currcard.Any()) // do not be tempted to use currcard.Count() > 0
{
// something with currcard; e.g.
System.Console.WriteLine("Currcard");
foreach(var card in currcard) // should do nothing if currcard has no elements
{
}
}
Related
After reading: http://forums.devart.com/viewtopic.php?f=31&t=22425&p=74949&hilit=IQueryable#p74949
It seems like I should use IQueryable to figure out if a entity's child table has a record or not.
My initial attempt was like:
Ace.DirDs.Any();
This line of code (or similar lines of code) could be run hundreds of times and was causing a huge performance issue.
So from reading the previous post in the link above I thought I would try something like:
IQueryable<DirD> dddd = CurrentContext.DirDs
.Where(d => d.AceConfigModelID == ace.ID).Take(1);
bool hasAChild = dddd.Any();
Would there be a better way?
There's no need for a Take(1). Plus, this one is shorter to type.
bool hasAChild = CurrentContext.DirDs.Any(d => d.AceConfigModelID == ace.ID);
I may be wrong, but I think Any() will still cause an initial Read() of the first row from the database server back to the client. You may be better getting a Count so you only get a number back:
bool hasAChild = CurrentContext.DirDs.Count(d => d.AceConfigModelID == ace.ID) > 0;
By the way this doesn't appear to be looking at a child table just DirDs.
In your example, you are materializing the IQueryable into an IEnumerable, and so the entire query is executed and you are then only just taking the first row in the result. Either of the previously exampled answers will be exponentially faster than this. Be careful when using Count as there is both a property Count and a method Count(). In order to avoid your original problem (and if you choose the Count route), you'll want to use the method Count() like in Rhumborl's example, otherwise it'll execute the query and give you the property Count of your IEnumerable that was returned. The method Count() essentially translates into a SQL COUNT whereas the method Any() translates into a SQL EXISTS (at least when working with Microsoft SQL Server). One can be more efficient than the other at this level depending on what your backend database is and which version of EF you're using.
My vote would be to always default to Any() and explore Count() if you run into performance troubles. There can still be performance costs with the method Count() at the database level, but that still depends on the database you're using.
Here's a good related answer: Linq To Entities - Any VS First VS Exists
I've been working for the first time with the Entity Framework in .NET, and have been writing LINQ queries in order to get information from my model. I would like to program in good habits from the beginning, so I've been doing research on the best way to write these queries, and get their results. Unfortunately, in browsing Stack Exchange, I've seem to have come across two conflicting explanations in how deferred/immediate execution works with LINQ:
A foreach causes the query to be executed in each iteration of the loop:
Demonstrated in question Slow foreach() on a LINQ query - ToList() boosts performance immensely - why is this? , the implication is that "ToList()" needs to be called in order to evaluate the query immediately, as the foreach is evaluating the query on the data source repeatedly, slowing down the operation considerably.
Another example is the question Foreaching through grouped linq results is incredibly slow, any tips? , where the accepted answer also implies that calling "ToList()" on the query will improve performance.
A foreach causes a query to be executed once, and is safe to use with LINQ
Demonstrated in question Does foreach execute the query only once? , the implication is that the foreach causes one enumeration to be established, and will not query the datasource each time.
Continued browsing of the site has turned up many questions where "repeated execution during a foreach loop" is the culprit of the performance concern, and plenty of other answers stating that a foreach will appropriately grab a single query from a datasource, which means that both explanations seem to have validity. If the "ToList()" hypothesis is incorrect (as most of the current answers as of 2013-06-05 1:51 PM EST seem to imply), where does this misconception come from? Is there one of these explanations that is accurate and one that isn't, or are there different circumstances that could cause a LINQ query to evaluate differently?
Edit: In addition to the accepted answer below, I've turned up the following question over on Programmers that very much helped my understanding of query execution, particularly the the pitfalls that could result in multiple datasource hits during a loop, which I think will be helpful for others interested in this question: https://softwareengineering.stackexchange.com/questions/178218/for-vs-foreach-vs-linq
In general LINQ uses deferred execution. If you use methods like First() and FirstOrDefault() the query is executed immediately. When you do something like;
foreach(string s in MyObjects.Select(x => x.AStringProp))
The results are retrieved in a streaming manner, meaning one by one. Each time the iterator calls MoveNext the projection is applied to the next object. If you were to have a Where it would first apply the filter, then the projection.
If you do something like;
List<string> names = People.Select(x => x.Name).ToList();
foreach (string name in names)
Then I believe this is a wasteful operation. ToList() will force the query to be executed, enumerating the People list and applying the x => x.Name projection. Afterwards you will enumerate the list again. So unless you have a good reason to have the data in a list (rather than IEnumerale) you're just wasting CPU cycles.
Generally speaking using a LINQ query on the collection you're enumerating with a foreach will not have worse performance than any other similar and practical options.
Also it's worth noting that people implementing LINQ providers are encouraged to make the common methods work as they do in the Microsoft provided providers but they're not required to. If I were to go write a LINQ to HTML or LINQ to My Proprietary Data Format provider there would be no guarantee that it behaves in this manner. Perhaps the nature of the data would make immediate execution the only practical option.
Also, final edit; if you're interested in this Jon Skeet's C# In Depth is very informative and a great read. My answer summarizes a few pages of the book (hopefully with reasonable accuracy) but if you want more details on how LINQ works under the covers, it's a good place to look.
try this on LinqPad
void Main()
{
var testList = Enumerable.Range(1,10);
var query = testList.Where(x =>
{
Console.WriteLine(string.Format("Doing where on {0}", x));
return x % 2 == 0;
});
Console.WriteLine("First foreach starting");
foreach(var i in query)
{
Console.WriteLine(string.Format("Foreached where on {0}", i));
}
Console.WriteLine("First foreach ending");
Console.WriteLine("Second foreach starting");
foreach(var i in query)
{
Console.WriteLine(string.Format("Foreached where on {0} for the second time.", i));
}
Console.WriteLine("Second foreach ending");
}
Each time the where delegate is being run we shall see a console output, hence we can see the Linq query being run each time. Now by looking at the console output we see the second foreach loop still causes the "Doing where on" to print, thus showing that the second usage of foreach does in fact cause the where clause to run again...potentially causing a slow down.
First foreach starting
Doing where on 1
Doing where on 2
Foreached where on 2
Doing where on 3
Doing where on 4
Foreached where on 4
Doing where on 5
Doing where on 6
Foreached where on 6
Doing where on 7
Doing where on 8
Foreached where on 8
Doing where on 9
Doing where on 10
Foreached where on 10
First foreach ending
Second foreach starting
Doing where on 1
Doing where on 2
Foreached where on 2 for the second time.
Doing where on 3
Doing where on 4
Foreached where on 4 for the second time.
Doing where on 5
Doing where on 6
Foreached where on 6 for the second time.
Doing where on 7
Doing where on 8
Foreached where on 8 for the second time.
Doing where on 9
Doing where on 10
Foreached where on 10 for the second time.
Second foreach ending
It depends on how the Linq query is being used.
var q = {some linq query here}
while (true)
{
foreach(var item in q)
{
...
}
}
The code above will execute the Linq query multiple times. Not because of the foreach, but because the foreach is inside another loop, so the foreach itself is being executed multiple times.
If all consumers of a linq query use it "carefully" and avoid dumb mistakes such as the nested loops above, then a linq query should not be executed multiple times needlessly.
There are occasions when reducing a linq query to an in-memory result set using ToList() are warranted, but in my opinion ToList() is used far, far too often. ToList() almost always becomes a poison pill whenever large data is involved, because it forces the entire result set (potentially millions of rows) to be pulled into memory and cached, even if the outermost consumer/enumerator only needs 10 rows. Avoid ToList() unless you have a very specific justification and you know your data will never be large.
Sometimes it might be a good idea to "cache" a LINQ query using ToList() or ToArray(), if the query is being accessed multiple times in your code.
But keep in mind that "caching" it still calls a foreach in turn.
So the basic rule for me is:
if a query is simply used in one foreach (and thats it) - then I don't cache the query
if a query is used in a foreach and in some other places in the code - then I cache it in a var using ToList/ToArray
foreach, by itself, only runs through its data once. In fact, it specifically runs through it once. You can't look ahead or back, or alter the index the way you can with a for loop.
However, if you have multiple foreachs in your code, all operating on the same LINQ query, you may get the query executed multiple times. This is entirely dependent on the data, though. If you're iterating over an LINQ-based IEnumerable/IQueryable that represents a database query, it will run that query each time. If you're iterating over an List or other collection of objets, it will run through the list each time, but won't hit your database repeatedly.
In other words, this is a property of LINQ, not a property of foreach.
The difference is in the underlying type. As LINQ is built on top of IEnumerable (or IQueryable) the same LINQ operator may have completely different performance characteristics.
A List will always be quick to respond, but it takes an upfront effort to build a list.
An iterator is also IEnumerable and may employ any algorithm every time it fetches the "next" item. This will be faster if you don't actually need to go through the complete set of items.
You can turn any IEnumerable into a list by calling ToList() on it and storing the resulting list in a local variable. This is advisable if
You don't depend on deferred execution.
You have to access more total items than the whole set.
You can pay the upfront cost of retrieving and storing all items.
Using LINQ even without entities what you will get is that deferred execution is in effect.
It is only by forcing an iteration that the actual linq expression is evaluated.
In that sense each time you use the linq expression it is going to be evaluated.
Now with entities this is still the same, but there is just more functionality at work here.
When the entity framework sees the expression for the first time, it looks if he has executed this query already. If not, it will go to the database and fetch the data, setup its internal memory model and return the data to you. If the entity framework sees it already fetched the data beforehand, it is not going to go to the database and use the memory model that it setup earlier to return data to you.
This can make your life easier, but it can also be a pain. For instance if you request all records from a table by using a linq expression. The entity framework will load all data from the table. If later on you evaluate the same linq expression, even if in the time being records were deleted or added, you will get the same result.
The entity framework is a complicated thing. There are of course ways to make it reexecute the query, taking into account the changes it has in its own memory model and the like.
I suggest reading "programming entity framework" of Julia Lerman. It addresses lots of issues like the one you having right now.
It will execute the LINQ statement the same number of times no matter if you do .ToList() or not. I have an example here with colored output to the console:
What happens in the code (see code at the bottom):
Create a list of 100 ints (0-99).
Create a LINQ statement that prints every int from the list followed by two * to the console in red color, and then return the int if it's an even number.
Do a foreach on the query, printing out every even number in green color.
Do a foreach on the query.ToList(), printing out every even number in green color.
As you can see in the output below, the number of ints written to the console is the same, meaning the LINQ statement is executed the same number of times.
The difference is in when the statement is executed. As you can see, when you do a foreach on the query (that you have not invoked .ToList() on), the list and the IEnumerable object, returned from the LINQ statement, are enumerated at the same time.
When you cache the list first, they are enumerated separately, but still the same amount of times.
The difference is very important to understand, because if the list is modified after you have defined your LINQ statement, the LINQ statement will operate on the modified list when it is executed (e.g. by .ToList()). BUT if you force execution of the LINQ statement (.ToList()) and then modify the list afterwards, the LINQ statement will NOT work on the modified list.
Here's the output:
Here's my code:
// Main method:
static void Main(string[] args)
{
IEnumerable<int> ints = Enumerable.Range(0, 100);
var query = ints.Where(x =>
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write($"{x}**, ");
return x % 2 == 0;
});
DoForeach(query, "query");
DoForeach(query, "query.ToList()");
Console.ForegroundColor = ConsoleColor.White;
}
// DoForeach method:
private static void DoForeach(IEnumerable<int> collection, string collectionName)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\n--- {0} FOREACH BEGIN: ---", collectionName);
if (collectionName.Contains("query.ToList()"))
collection = collection.ToList();
foreach (var item in collection)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write($"{item}, ");
}
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\n--- {0} FOREACH END ---", collectionName);
}
Note about execution time: I did a few timing tests (not enough to post it here though) and I didn't find any consistency in either method being faster than the other (including the execution of .ToList() in the timing). On larger collections, caching the collection first and then iterating it seemed a bit faster, but there was no definitive conclusion from my test.
I've got a LINQ query that's returning no results when I know that it should be returning at least one. I'm building up the query dynamically. I looked at the result set in the debugger right before I get to the line that filters out all of the results and it contains hundreds of rows. After this line, it contains 0 when it really should contain at least one.
query = query.Where(x =>
x.Lineages.FirstOrDefault().Sire.Contains(options.PedigreeContains));
'x' in this case represents an entity called 'Horse'. 'options.PedigreeContains' is just a string value. The Lineages table looks like this:
ID HorseID Sire Dam etc...
I can even pull up a Horse entity in the debugger (the one I know should be returned as a result), inspect the Lineages property and see it fully populated, including the Sire value that matches my search. So everything SEEMS like it should be working, except there's obviously some issue with the LINQ query that I'm using.
Does anyone see anything inherently wrong with what I'm doing that would cause this to filter out results that I know should be there?
EDIT: For clarification, it's a 1-to-1 relationship. I know the Lineages object exists, I know there's only one, and I know it matches. It's just for some reason it's returning zero results so I thought there might be a problem with the way I wrote the query. If that query should work the way it's written though (minus all of the extra "possibilities" if no lineages exist, more than one, etc) then it must be an issue somewhere else in my code.
What if FirstOrDefault returns the "Default"? You'll get a NullReferenceException.
You are providing no means to order the Lineages, if the first one returned does not have the desired Sire containing option.PedigreeContains. In such a case, the result set would be empty, regardless of the other Sire's in the Lineages.
Actually answring your question: No. There is nothing inherently wrong with your query. It must be an issue somewhere else in your query construction, in the database structure or in your data.
When debugging, instead of enumerating and verifying the result count, copy the query expression value and look what the generated SQL looks like. You can do that before and after altering the IQueryable query. Other suggestions like #Jalalx use of .Any() to avoid what #John Saunders points out.
If you do FirstOrDefault() where you have it, aren't you taking the first of what could be many sires, so if a later one matches your where you won't find it?
query = query.Where(x =>
x.Lineages.FirstOrDefault(lineage => lineage.Sire.Contains(options.PedigreeContains))).Sire;
I am trying to check to see if any results were returned from an entity framework query before acting upon it, I'm trying to use the code :-
var shoppingCartSessions = from c in context.ShoppingCartSessions where c.UserId == gUserID select c;
if (shoppingCartSessions.First() != null)
{
}
However I get the error
Sequence contains no elements
I have checked around stack and found that I can replace .First with .FirstOrDefault however I wanted to check if this is the correct way to be checking for existence of elements. Is there a better way rather than trying to fetch the item and then checking it?
Use Any():
var shoppingCartSessions = from c in context.ShoppingCartSessions
where c.UserId == gUserID
select c;
if (shoppingCartSessions.Any())
{
//not empty
}
Have you tried checking .Count() > 0 ?
EDIT:
As stated by Mahmoud Gamal, using Any() should render slightly better performance, since it will execute an EXISTS query, rather than a COUNT() on the DB, and you ultimately don't care about the exact amount.
I have a rather ugly service job that runs through a legacy database and compares it to our production database:
if (vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number) != null) {
var oldDbContractItem = vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number).First();
// check to see if there were changes
if (oldDbContractItem.DateStamp != vendorContractItem.Date_Stamp)
{
oldDbContractItem.Update(vendorContractItem);
}
}
I will get an error on var oldDbContratItem, "Sequence contains no elements", yet I just did a != null check. This must be simple, what's going on?
If I could teach people just one thing about LINQ it's this: the value of a query expression is an object that represents the query, not the results of the query. Fundamentally that's your problem; you're treating the query as its results. A query isn't a result any more than a restaurant is a club sandwich. A restaurant is a device which produces club sandwiches; a query is a device that produces results.
This is the test against null you are doing:
vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number) != null
That will always be true; That will always return at least an empty sequence... never a null.
You might be meaning to test that its length is greater than 0?
There's an easier way, though, IMO. Call FirstOrDefault() instead of First() and leave out the pre-test completely. Then instead, test if the result of FirstOrDefault() is null.
var oldDbContractItem = vendorContract.Item
.Where(x => x.ItemNumber == contractItem.Item_Number).FirstOrDefault();
if(oldDbContractItem != null) //would be null if there are no items
{
// check to see if there were changes
if (oldDbContractItem.DateStamp != vendorContractItem.Date_Stamp)
{
oldDbContractItem.Update(vendorContractItem);
}
}
}
Because your query returned a container, it just happened to be empty, the null check is on the return not what the return contains.
try this instead...
if (vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number).Any())
{
.....
}
Don't run the query twice. It's inefficient and may introduce a race condition into your code. Also, your logic is much better supported by either using IEnumerator<T> directly, or with a foreach loop.
Use either:
var result = vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number).GetEnumerator();
if (result.MoveNext) {
var oldDbContractItem = result.Current;
// ...
}
or
foreach (var oldDbContractItem in vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number)) {
// ...
break;
}
A sequence with no elements is still an object.
Where can return a non-null value, but still resolve to a sequence containing no elements. In your failing statement you are using something else, which is Where().First(). That will be null if the sequence from Where is indeed empty.
There is difference between null and an empty sequence (e.g. something similar to new List<T>()). What you want to do is to use Any() to check whether the sequence contains any elements, or rather replace First() with FirstOrDefault(), which returns null if the sequence contains no element. (If you use that, make sure that null is not a valid value that could be returned by First()).
After using a fix from the accepted answer, you can further debug the LINQ situation (if need be) by using the following steps. LINQ is an exciting technology but takes a while to wraps ones' head around it - a bit of a paradigm shift I would say. Eric's answer hit the nail on the head because he likely helped build the stuff!
Debugging Steps for LINQ
To deal with the issue of no results from the second statement change .First() to .FirstOrDefault() If nothing is found it will return the default value of the data type - if the data type is a class it will return a null value. Your second statement should then work with a null check too and without error.
Then you can debug your LINQ statement to find out why it's doing what it does.
if using LINQ to SQL, Intellisense in Visual Studio 2010 will show you the SQL generated when you hover over a query variable (not the result of a query). If you need the visualizer for VS 2008 it's here
Similarily if you're using LINQ to Entity Framework, you can get the generated SQL using the visualizer plugin here.
I always take the generated SQL from these tools, paste it directly into a query window and run it there. It will show you the empty set you're getting back and if that's a problem you can further debug it in this manner of visualizing the generated statements.