RavenDB + Linqpad, I get Method not supported: GroupBy - ravendb

I try to run this query Inside Linqpad when connected to RavenDB:
from c in Query<Tournament.Models.Matches>()
group c by c.Location into g
select g
I get the following error:
Could not understand expression: .GroupBy(c => c.Id).Select(g => g)
Method not supported: GroupBy
at Raven.Client.Linq.RavenQueryProviderProcessor`1.GetLuceneQueryFor(Expression expression)
at Raven.Client.Linq.RavenQueryProviderProcessor`1.Execute(Expression expression)
at Raven.Client.Linq.RavenQueryProvider`1.Execute(Expression expression)
at Raven.Client.Linq.RavenQueryProvider`1.System.Linq.IQueryProvider.Execute(Expression expression)
at Raven.Client.Linq.RavenQueryInspector`1.GetEnumerator()
at Raven.Client.Linq.RavenQueryInspector`1.System.Collections.IEnumerable.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
When run a simple query with no aggregation it runs ok.
I added references to Raven.Client.Lighweight and Raven.Abstaractions and still the same error
I'm probably missing something stupid.

Related

How can I use a method to add a filter on a property in Entity Framework Core?

I need to conditionally add a filter to particular dates in a query. There are common preconditions and the filter will be the same. Therefore I would like the common code to be in a method which can perform these checks and then have the consumer pass in the property which the filter should be applied to (could be applied to multiple).
Here is a simplified version of my code.
var query = dbContext.Documents.AsQueryable();
query = FilterDocumentsByDate(query, x => x.CreatedDate);
query = FilterDocumentsByDate(query, x => x.SubmittedDate);
private IQueryable<Document> FilterDocumentsByDate(IQueryable<Document> query, Func<Document, DateTime> propertyToSearch)
{
query = query.Where(x => propertyToSearch(x).Year > 2000);
return query;
}
When I look at the query in SQL profiler, I can see that the query is missing the WHERE clause (so all documents are being retrieved and the filter is being done in memory). If I copy/paste the code inline for both dates (instead of calling the method twice) then the WHERE clause for the both dates are included in the query.
Is there no way to add a WHERE condition to an IQueryable by passing a property in a Func which can be properly translated to SQL by Entity Framework?
EF is unable to understand your query, so it breaks and executes WHERE clause in memory.
The solution is creating dynamic expressions.
var query = dbContext.Documents.AsQueryable();
query = FilterDocumentsByDate(query, x => x.CreatedDate.Year);
query = FilterDocumentsByDate(query, x => x.SubmittedDate.Year);
private IQueryable<Document> FilterDocumentsByDate(IQueryable<Document> query, Expression<Func<Document, int>> expression)
{
var parameter = expression.Parameters.FirstOrDefault();
Expression comparisonExpression = Expression.Equal(expression.Body, Expression.Constant(2000));
Expression<Func<Document, bool>> exp = Expression.Lambda<Func<Document, bool>>(comparisonExpression, parameter);
query = query.Where(exp);
return query;
}
I am sorry, I haven't run this myself, but this should create WHERE statement. Let me know how it goes.

Reference subquery fields in QueryDSL

I have to build a query in QueryDSL with a subquery, like this:
Expression<String> caseExpression = new CaseBuilder()
...;
Expression<?>[] queryProjection={
table.parameter1,
caseExpression
};
Expression<?>[] subqueryProjection={
table.parameter1.as("alias1"),
table.parameter2.as("alias2"),
table.parameter3.as("alias3"),
table.parameter4.as("alias4")
};
SQLSubQuery subQuery = new SQLSubQuery()
.from(table)
.where(...);
JPASQLQuery query = new JPASQLQuery(entityManager, ORACLE_TEMPLATE)
.from(subQuery.list(subqueryProjection));
query.list(queryProjection);
I am getting the following exception:
9/10/2014 09:45:55 AM org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() para servlet rtve-rest lanzó excepción
java.sql.SQLException: ORA-00904: "TABLE"."PARAMETER1": invalid identifier
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:813)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1049)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:854)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1154)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3415)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:93)
at sun.reflect.GeneratedMethodAccessor54.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at $Proxy78.executeQuery(Unknown Source)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:829)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)
at org.hibernate.loader.Loader.doList(Loader.java:2438)
at org.hibernate.loader.Loader.doList(Loader.java:2424)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2254)
at org.hibernate.loader.Loader.list(Loader.java:2249)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:331)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1784)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:229)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:156)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:257)
at com.mysema.query.jpa.sql.AbstractJPASQLQuery.list(AbstractJPASQLQuery.java:145)
This is caused because the field in my queryProjection is not the same as in my subqueryProjection. This field has to be the same as in the subquery ("alias1").
How could I reference a field by its alias? Or how could I reference a field in a subquery from outside it?
Thank you very much in advance
You need to use a Path instance with alias1 as the name or get rid of the aliasing. The simplest way to create that Path is
Expressions.path(Object.class, "alias1")
Replace Object with a more specific type if needed.
I managed to do it with Expressions.stringTemplate:
Expression<?>[] queryProjection={
Expressions.stringTemplate("alias1"),
caseExpression
};

Strange error on stringed Linq calls

I inherited this code that takes an IEnumerable and performs a series of Selects on it and then attempts to call Sum on the remaining records after the Selects are performed. The code reads as:
var totalrecs = records.Select(row => new RowInfo(RowID = row.RowID, SomeData = row.SomeData})
.Select(ri => new {RowInfo = ri, XMLData = GetXMLFileForRecord(ri)})
.Select(data => ParseAndUpdateRecords(data.RowInfo, data.XmlData))
.Sum();
where 'records' is an IEnumerable.
The error is for attempting to convert a decimal to a long and from the StackTrace seems to be occurring when calling Sum on the Iterator that results from the three Select calls.
The stack trace is:
Exception:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot implicitly convert type 'decimal' to 'long'. An explicit conversion exists (are you missing a cast?)
at CallSite.Target(Closure , CallSite , Object )
at RecordCapture.Controller.<CaptureAndUpdateRecords>b__10(Object row)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Sum(IEnumerable`1 source)
at RecordCapture.Controller.CaptureAndUpdateRecords()
at RecordCapture.Controller.<Start>b__1()
StackTrace: at CallSite.Target(Closure , CallSite , Object )
at RosterCapture.Controller.<CaptureAndUpdateRosters>b__10(Object row)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Sum(IEnumerable`1 source)
at RecordCapture.Controller.CaptureAndUpdateRecords()
at RecordCapture.Controller.<Start>b__1()
The Selects return an Iterator and there does not seem to be any way to get an accurate count of what the result of the Selects is.
Interestingly, if records is empty, calling Sum simply returns a zero and does not throw an error.
Do you want to Sum integers or decimals? Use the Generic type appropriate, and cast the result if necessary. See http://msdn.microsoft.com/en-us/library/system.linq.enumerable.sum.aspx for the overload list.
I figured this out. The Stack Trace was misleading.
The issue was in building up the RowInfo object in my code... the RowID was a long and the variable that the property was setting it's value to was a decimal.
I believe the error occurred in the Sum call because of lazy loading where the setting of the attributes was not done until that call was made and the data was needed.

Linq to sql constantly returns null

I have the following SQL query:
SELECT DISTINCT
Participant.BackgroundTrainingID,
Location.TrainingSite
FROM Registration, ProgramLocation, Participant, Program, Location
WHERE ProgramLocation.LocationID = Location.LocationID
AND ProgramLocation.ProgramID=Registration.ProgramID
AND Registration.ParticipantID=Participant.ParticipantId
I wrote the following LINQ to SQL to match the query above:
var trainingsiteinfo = (from c in db.ProgramLocations
from n in db.Registrations
from l in db.Participants
from h in db.Locations
where c.LocationID == h.LocationID
&& c.ProgramID == n.ProgramID
&& n.ParticipantID == l.ParticipantId
select new {
h.TrainingSite,
l.BackgroundTrainingID }).Distinct();
The SQL query works fine but LINQ constantly returns null.
I use Linqer http://www.sqltolinq.com/ when i get out of ideas :-) Aswell it speeds up conversion jobs.
Make sure your db context isn't going out of scope before you have bound your results. You can test this by adding .ToList() after your .Distinct() to force eager loading of the results.
Your linq code has an unclosed } bracket in the select statement

VB.NET - LINQ to SQL - How do I add in Row_Number to a LINQ to SQL query in VB.NET?

How do I add ROW_NUMBER to a LINQ query or Entity?
How can I convert this solution to VB.NET?
var start = page * rowsPerPage;
Products.OrderByDescending(u => u.Sales.Count())
.Skip(start)
.Take(rowsPerPage)
.AsEnumerable()
.Select((u, index) => new { Product = u, Index = index + start }); // this line gets me
I'm having trouble porting that last line. I have been unable to locate a VB.NET example.
I'm actually not looking for any paging functionality like the example provides, just good old-fashioned Row_Number(Order By X) row index.
LinqToSql can't do a Row_Number(Order By X) in the database.
The c# code you posted does it against in-memory instances by calling Enumerable.Select
On the msdn page for Enumerable.Select, there's a vb.net example.
Here is a working example that demonstrates the projection of a row index in VB.NET:
Dim R = (
From P In DB.Products Select P
).AsEnumerable().Select(
Function(Product, index) New With {index, Product}
)
Response.Write(R(12).Product.Doc_width.ToString()) 'Access object members
Response.Write(R(12).index.ToString() 'Access Row Index