In our appliction we have a piece of code with some Linq-queries (EF) that sometimes throws an exception.
This has only happened to the end user, and we are not able to reproduce it so far.
From the logfile we got the following stacktrace for the exception:
System.InvalidOperationException: Sequence contains no elements
at System.Linq.Enumerable.Single[TSource](IEnumerable1 source)
at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3[TResult](IEnumerable1 sequence)
at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable1 query, Expression queryRoot)
at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
at System.Linq.Queryable.Count[TSource](IQueryable1 source)
at MT3.uctXGrid.LoadLayout(String strUniqueID, Boolean rethrowException, List`1 visibleColumns)
In the method LoadLayout there are only 2 instances of Count(), and they are just operating on standard IQueryables which interrogate an entity type based on one integer field and select all fields (no aggregations or anything).
ex:
from p in cxt.genData where datId = ID
In the stacktrace, it seems like internally .Single() is being used which could throw an exception if there are no records.
But why is it using single if we are just calling .Count() ?
How can a query like
(from p in cxt.genData where datId = ID).Count()
throw a "sequence contains no elements" exception?
We have had other strange problems with queries as well, I'm starting to wonder if there are any issues with our version of EF maybe.
We are still on 4.0 at the moment. (Standard version which came with VS2010).
Has anyone got an idea what could be going on here?
Update:
Here are the Linq-to-Entities queries we actually use
Dim qryLastLayout = From t In oContext.genGridLayouts Where t.layID = intCurrentLayoutID
If Not IsNothing(qryLastLayout) AndAlso qryLastLayout.Count <> 0 Then
Dim qryPrintSettings = From p In oContext.genPrintSettings Where p.prtDefault = True
If Not IsNothing(qryPrintSettings) AndAlso qryPrintSettings.Count <> 0 Then
Have you tried using the .Any() method?
if(cxt.genData.Any(x => x.datId == ID))
{
// do something here
}
One thing to be aware of wrt Linq to Entities is that the semantics of Count() are not those of .NET but those of the underlying datasource (somewhat undermining the whole language-integration aspect, but oh well...). I don't think this can cause issues like yours, but you never know.
MSDN link with more details: http://msdn.microsoft.com/en-us/library/vstudio/bb738551.aspx#sectionSection5
Related
I have a Worker entity with string Name property, and just want to filter all Workers whose Name contains some specific string (from frontend text input).
When I do the filtering with:
_context.Workers.Where(w => w.Name.ToUpper().Contains(filter.ToUpper()).ToList()
it is working but it does not solves some specific diacritics in filter term.
When i try with:
var compareInfo = CultureInfo.InvariantCulture.CompareInfo;
_context.Workers.Where(w => compareInfo.IndexOf(w.Name, filter, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) > -1).ToList()
i get System.NullReferenceException: 'Object reference not set to an instance of an object.'
and console An exception occurred in the database while iterating the results of a query for context type 'Project.MyDbContext'.
I've also tried with
_context.Workers.Where(w => compareInfo.IndexOf((w.Name??""), filter, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) > -1).ToList()
to perform a null check, but same.
Did anyone have same problem, or maybe idea what could be changed here so I could accompiish searching with diacritics?
Thx!
I was having some performance issues using SharpRepository, and after playing around the SQL Query Profiler I found the reason.
With EF I can do stuff like this:
var books = db.Books.Where(item => item.Year == '2016');
if (!string.IsNullorEmpty(search_author))
books = books.Where(item => item.Author.Contains(search_author);
return (books.ToList());
EF will not really do anything until books is used (last line) and then it will compile a query that will select only the small set of data matching year and author from the db.
But SharpRepository evaluates books at once, so this:
var books = book_repo.Books.FindAll(item => item.Year == '2016');
if (!string.IsNullorEmpty(search_author))
books = books.Where(item => item.Author.Contains(search_author);
return (books.ToList());
will compile a query like "select * from Books where Year == '2016'" at the first line, and get ALL those records from the database! Then at the second line it will make a search for the author within the C# code... That behaviour can be a major difference in performance when using large databases, and it explains why my queries timed out...
I tried using repo.GetAll().Where() instead of repo.FindAll().... but it worked the same way.
Am I misunderstanding something here, and is there a way around this issue?
You can use repo.AsQueryable() but by doing that you lose some of the functionality that SharpRepository can provide, like caching or and aspects/hooks you are using. It basically takes you out of the generic repo layer and lets you use the underlying LINQ provider. It has it's benefits for sure but in your case you can just build the Predicate conditionally and pass that in to the FindAll method.
You can do this by building an Expression predicate or using Specifications. Working with the Linq expressions does not always feel clean, but you can do it. Or you can use the Specification pattern built into SharpRepository.
ISpecification<Book> spec = new Specification<Book>(x => x.Year == 2016);
if (!string.IsNullorEmpty(search_author))
{
spec = spec.And(x => x.Author.Contains(search_author));
}
return repo.FindAll(spec);
For more info on Specifications you can look here: https://github.com/SharpRepository/SharpRepository/blob/develop/SharpRepository.Samples/HowToUseSpecifications.cs
Ivan Stoev provided this answer:
"The problem is that most of the repository methods return IEnumerable. Try repo.AsQueryable(). "
I have this Linq To Entites query below. When I execute this query from a Console Application, it produces SQL and executes perfectly.
But when I execute it from a web application, I get an error message that says the Min() function is not recognized by Linq To Entites and it cannot be translated to a store expression.
It is EXACTLY the same query. Both project have the same settings (concerning EF 6) in their config files, and they reference the same assemblies.
from ce in db.CustomEvents
where ce.fld_start > DateTime.Now
group ce by ce.fld_ownerId into g
select new
{
fld_ownerId = g.Key,
next_appointement_date = g.Min(i => i.fld_start)
}
It seems this happens only when the Min aggregate is on DateTime property. I hadn't this issue when I had Min on decimals, for instance.
The error message I get when I execute this in the web site is this
LINQ to Entities does not recognize the method 'System.Nullable`1[System.DateTime]
Min[CustomEvent](System.Collections.Generic.IEnumerable`1[CustomEvent],
System.Func`2[CustomEvent,System.Nullable`1[System.DateTime]])'
method, and this method cannot be translated into a store expression.
But when I execute it from the Console app, it successfully generates the SQL statement below
SELECT
1 AS [C1],
[GroupBy1].[K1] AS [fld_ownerId],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[fld_ownerId] AS [K1],
MIN([Extent1].[fld_start]) AS [A1]
FROM [dbo].[mtbl_CustomEvent] AS [Extent1]
WHERE [Extent1].[fld_start] > (SysDateTime())
GROUP BY [Extent1].[fld_ownerId]
) AS [GroupBy1]
Does anyone have a clue on what is happening?? Why the same query generates SQL when run in the console app, but fails with an exception when run in the web site??
UPDATE:
It seems that the problem was an ambiguity between two different implementations of Min<T>(this IEnumerable<T>) (.net's implementation, and our own implementation). Removing the "using OurLibrary;" namespace from the file fixed the problem.
After vittore's suggestion to use extension methods syntax we found that the problem was that in the web project we referenced one of our libraries that included an implementation of Min<T>(this IEnumerable<T>), and we also had the using OurLibrary.Namespace; directive in the file where the linq query was.
When we used the linq syntax, the compiler picked our implementation of Min for the query and did not throw any errors. Then, at runtime, the LINQ to Entities framework crashed because it could not recognise our implementation of Min.
from ce in db.CustomEvents
where ce.fld_start > DateTime.Now
group ce.fld_start by ce.fld_ownerId into g
select new
{
fld_ownerId = g.Key,
next_appointement_date = g.Min()
}
Here there was no compiler error.
But when we used the extension method syntax, the compiler stopped with an ambiguity error, and that's how we identified the problem.
db.CustomEvents
.Where(ce => ce.fld_start > DateTime.Now)
.GroupBy(ce => ce.fld_ownerId, ce => ce.fld_start)
.Select(g => new { g.Key, next_appointement_date = g.Min() })
Here the compiler threw an error of ambiguous call to .Min
It's weird that the compiler does not recognise the ambiguity in the Linq syntax. After all, linq is only syntactic sugar.
I keep getting a system.outofmemoryexception:
Exception of type 'System.OutOfMemoryException' was thrown.
at System.Collections.Generic.List1.set_Capacity(Int32 value)
at System.Collections.Generic.List1.EnsureCapacity(Int32 min)
at System.Collections.Generic.List1.Add(T item)
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
at CIGDataLibrary.Archive.ArchiveCycleData(String applicationName)
in c:!TFS\SCCSoftware\Commercial\CIG\Wagering\CIGDataLibrary\files\Archive.cs:line 571
Code at line 571:
List<Guid?> cycleData = Queries.Current.GetCycleDataArchiveList();
The method:
public static List<Guid?> GetCycleDataArchiveList()
{
using (var dbContext = new CIGDataModels.CIGDBStoredProcModels())
{
return dbContext.usp_arch_GetCycleData().ToList();
}
}
And the meat of the stored procedure:
SELECT TOP 1000 gpCycleData_Id FROM CIGDB.dbo.cig_Cycle_gpCycleData
WHERE [TimeStamp] < DATEADD(HH, 3, DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())))
ORDER BY [TimeStamp]
Any thoughts on why this is occurring? It should be returning 1000 records (just a list of GUIDs) so shouldn't be throwing a fit, right? I've taken the SP down to TOP 1 but still results in same error.
Your production database is returning too many rows. It's likely missing the TOP n clause within the stored procedure, hence it's returning so much data that your application is running out of memory.
As you say you have edited the stored proc to only return a single row and it's still causing an error, there must be another factor.
Assuming that there's nothing more to the procedure than you have posted, some possible reasons:
A trigger is affecting the output in some way.
Entity framework is calling a different procedure. Check the content of your model to determine the correct procedure is being called.
Another procedure exists in a different schema. For example, your app logs into the database with username myApp and when it calls MyProc it's resolving to myApp.MyProc instead of dbo.MyProc.
Ok, I figured out the issue and it has run as expected.
Contrary to the exception's stack trace, the error was on line 572, not 571.
That line was
List<Guid> arch_gpCycle = dbarchContext.cig_Cycle_gpCycleData.Select(s => s.gpCycleData_Id).ToList();
And that resulted in the system.outofmemoryexception. I have since changed it to a compiled query that returns a list of Guids and it has run successfully.
I'm working on a c# project that use a Versant Object Database back end and I'm trying to build a query that contains an arithmetic operator. The documentation states that it is supported but lack any example.
I'm trying to build something like this:
SELECT * FROM _orderItemObject WHERE _qtyOrdered - _qtySent > 0
If I try this statement in the Object Inspector I get a synthax error near the '-'.
Anyone has an example of a working VQL with that kind of statement?
Thanks
I am not sure that the Object Inspector will know the syntax for the arithmtic expression. However, in your code you should be referring to the fully qualified class. Then the syntax you are using should be perfectly fine.
Query query = new Query( session,
"select * from com.yourCompany.yourClass where _qtyOrdered - _qtySent > 0 ");
QueryResult result = query.execute();
I just tried this out on one of my classes and it worked fine.
Cheers,
-Robert
With C# and OQL you have to make sure you select the proper class extent. This is done by adding the "Extent" suffix to the class name. For example, in my Pet class I would identify all the pets with "PetExtent" in the OQL string.
Class members are accessed in the predicate by defining a local moniker, p in the code below. Any arithmetic expressions will be evaluated by the query engine.
string query="SELECT * FROM PetExtent AS p WHERE p.Name = \"Ferris\" AND (p.age + 5) > 4";
IQueryResult result = scope.GetOqlQuery(query).Execute();
foreach (object o in result)
Out(o.ToString());
The best way to test OQL with Versant's C# binding is to use the OQL Query Browser integrated into Visual Studio. Look under the Versant Menu drop down in Visual Studio.
Best Regards,
Derek