4

I am trying to run a simple custom query that is returned into a custom object, however, I keep running into an error and I have no idea what is wrong. The query runs just fine in SQL Server Management Studio.

public class MyClass
{
    public Nullable<int> EligibleCredits { get; set;}
    public Nullable<int> ReadyForSubmissionCredits { get; set; }
    public Nullable<int> RedeemedCredits { get; set; }
}

Main Method:

var query = @"SELECT 
    (select count(*) from MyTable where UserId = @userId and [Status] = 0 and Year(EarnDate) >= (select Year(getdate()) -@years)) as EligibleCredits,
    (select count(*) from MyTable where UserId = @userId and [Status] = 1 and Year(EarnDate) >= (select Year(getdate()) -@years)) as ReadyForSubmissionCredits,
    (select count(*) from MyTable where UserId = @userId and [Status] = 2 and Year(EarnDate) >= (select Year(getdate()) -@years)) as RedeemedCredits";

var objectQuery = new ObjectQuery<MyClass>(query, ((IObjectContextAdapter)this).ObjectContext);
objectQuery.Parameters.Add(new ObjectParameter("userId", userId));
objectQuery.Parameters.Add(new ObjectParameter("years", years));

return objectQuery.FirstOrDefault();

The error that I get is:

The query syntax is not valid. Near term '*', line 2, column 39.

This query runs fine in SQL Server Management Studio.

Also, according to this article, I'm doing it correctly: https://msdn.microsoft.com/en-us/library/bb738521(v=vs.100).aspx

3
  • Are userId and years ints? Are they nullable? Commented Jan 31, 2018 at 20:20
  • First, why aren't you using EF rather than a raw SQL query? Second, your raw SQL query could be improved with a structure like select count(UserId), CASE WHEN [Status] = 0 THEN 'EligibleCredits' WHEN [Status] = 1 THEN 'ReadyForSubmissionCredits' WHEN [Status] = 2 THEN 'RedeemedCredits' END AS CreditType from MyTable where UserId = @userId and [Status] IN (0,1,2) and Year(EarnDate) >= (select Year(getdate()) -@years)) GROUP BY [Status]. Commented Jan 31, 2018 at 20:26
  • 2
    Apparently Entity SQL query is not the same as SQL query. The exception is thrown by EF SQL query parser. Rather than obsolete ObjectContext APIs, use the EF6 preferred context.Database.SqlQuery<MyClass>(...) - look at the help how to specify parameters. Commented Jan 31, 2018 at 20:37

2 Answers 2

2

This is a bug in the EntityFramework query parser. All I can do, is to provide you with a workaround (which BTW, may even run faster):

var query = @"SELECT 
    ISNULL(SUM(CASE WHEN [Status] = 0 THEN 1 ELSE 0 END),0) as EligibleCredits,
    ISNULL(SUM(CASE WHEN [Status] = 1 THEN 1 ELSE 0 END),0) as ReadyForSubmissionCredits,
    ISNULL(SUM(CASE WHEN [Status] = 2 THEN 1 ELSE 0 END),0) as RedeemedCredits
    FROM MyTable 
       WHERE UserId = @userId 
       AND Year(EarnDate) >= Year(getdate()) - @years";

var objectQuery = new ObjectQuery<MyClass>(query, ((IObjectContextAdapter)this).ObjectContext);
objectQuery.Parameters.Add(new ObjectParameter("userId", userId));
objectQuery.Parameters.Add(new ObjectParameter("years", years));

return objectQuery.FirstOrDefault();

Note that if this is an instance of DbContext, you can simplify your code as follows:

var query = @"SELECT 
    ISNULL(SUM(CASE WHEN [Status] = 0 THEN 1 ELSE 0 END),0) as EligibleCredits,
    ISNULL(SUM(CASE WHEN [Status] = 1 THEN 1 ELSE 0 END),0) as ReadyForSubmissionCredits,
    ISNULL(SUM(CASE WHEN [Status] = 2 THEN 1 ELSE 0 END),0) as RedeemedCredits
    FROM MyTable 
       WHERE UserId = @p0 -- <== NOTE THE PARAM NAME HERE AND BELOW
       AND Year(EarnDate) >= Year(getdate()) - @p1";
return new this.Database.SqlQuery<MyClass>(query, userId, years).FirstOrDefault();

This last approach also works with your original query.

Sign up to request clarification or add additional context in comments.

2 Comments

Essentially the bug is the fact that it cannot fill out the null object?
@Bojan No, it's parsing the SQL statement. EF needs to parse the query so it knows how to assign the output to objects in .NET. Normally, objectQuery.ToTraceString() would output the generated SQL statement, but in this case, it throws the same exception, even before execution takes place.
0

ExecuteStoreQuery worked for me, for the same error. Sample below:

IList<MyClass> contactList =
            (((IObjectContextAdapter) model).ObjectContext.ExecuteStoreQuery<MyClass>(strString))
            .ToList<MyClass>();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.