I'm getting an error for the following:
var answerList = (from answer in db.QuestionAnswers
where answer.tLoginID.Equals(tId) && answer.pLoginID.Equals(pId)
&& answer.Submitted.Equals(submittedVal)
select answer).ToList();
The error is:
Unable to create a constant value of type 'System.Object'. Only
primitive types or enumeration types are supported in this context.
However, when I change it to:
var answerList = (from answer in db.QuestionAnswers
where answer.tLoginID.Equals(tId) && answer.pLoginID.Equals(pId)
select answer).ToList();
Then I do this:
answerList.Where(x => x.Submitted.Equals(submittedVal));
It works... What am I missing? To me these statements are doing the same thing. But I'm not sure why it is working like this.
UPDATE:
I figured out after looking at the link that #SergeyLitvinov provided about .Equals that the column I was checking Submitted was actually a Boolean instead of an Integer once I made the types the same my statements worked. Although I did change it from .Equals to ==.
The error is from the LINQ to Entities query provider which is attempting to transform your query expression into a SQL statement. Your second example enumerates your LINQ to Entities query prior to testing for Submitted.Equals(submittedVal), which mean you're using standard LINQ to Objects in local memory (i.e. it is not converted to SQL).
Related
The full error LINQ throws is:
Unable to create a constant value of type
'Apple.Models.ADMIN_USER_ROLES'. Only primitive types or enumeration
types are supported in this context.
Code that produces error (on EF 4) is shown below.
var userID = 1;
List<ADMIN_ROLE> roles = db.ADMIN_ROLES.Where(r =>
db.ADMIN_USER_ROLES.Any(ur =>
ur.ID_USER == userID && ur.ID_ROLE == r.ID)).ToList();
This error doesn't happen in LINQPad or in my other (EF 5) project.
Hardcoding the value 1 in the query instead of userID, also, doesn't show any errors.
Project was copied from another PC, where it works.
Refactoring the splitting the linq into two queries would work, but I can't do that.
Does anyone know what causes this, so I avoid any refactoring.
UPDATE 1: This happens only in the nested queries, otherwise it works. See Mahyar's answer.
If you are insisting on working on IQueryables you can use the LINQ below
var userRoles = db.ADMIN_USER_ROLES.Where(ur => ur.ID_USER == userID);
var rols = (from r in db.ADMIN_ROLES
where (from ur in userRoles select ur.ID_ROLE).Contains(r.ID)
select r).ToList();
Most probably your issue will be fixed by adding a ToList or .AsEnumerable() method, like this:
db.ADMIN_ROLES.ToList().Where
Or:
db.ADMIN_USER_ROLES.ToList()
With .ToList() after data is loaded, any further operation (such as select) is performed using Linq to Objects, on the data already in memory.
I am storing ZIP codes in my database and trying to convert the following T-SQL to Linq to Entity:
SELECT *
FROM Regions
WHERE EndZip >= '12345'
I'm trying something like the following code:
var result = this.DbContext.Regions.Where(e => e.EndZip.CompareTo("12345") >= 0);
but I get an EntityCommandExecutionException: "The binary operator GreaterThanOrEqual is not defined for the types 'System.String' and 'System.String'."
I was able to do this if I convert my IQueryable to an IEnumerable, but I would like this query to be executed in SQL for performance reasons.
Does anyone know how I can compare strings in Linq to Entity?
There is a restricted set of Functions supported in Linq to Entities.
String comparisons are limited.
Linq to entity Docu
then see inside links
Supported Linq to Entity functions
The intro says most of it
This section provides information about the Language-Integrated Query (LINQ) standard query operators that are supported or unsupported in LINQ to Entities queries. Many of the LINQ standard query operators have an overloaded version that accepts an integer argument. The integer argument corresponds to a zero-based index in the sequence that is being operated on, an IEqualityComparer, or IComparer. Unless otherwise specified, these overloaded versions of the LINQ standard query operators are not supported, and attempting to use them will throw an exception.
While I would, in general, consider treating a ZipCode as a number (instead of as a string), being a particular heinous thing to do, in this case, it seems to work:
from e in DbContext.Regions
where Convert.ToInt32(a.EndZip) >= 12345
select e
UPDATE:
Since there will be Canadian postal code (which we'll assume we do not want in our ">= 12345" search:
from e in DbContext.Regions
where DbContext.IsNumeric(a.EndZip) && Convert.ToInt32(a.EndZip) >= 12345
select e
To get that to work, you'll need let Linq know about IsNumeric
partial class MyDataContext
{
[Function(Name = "ISNUMERIC", IsComposable = true)]
public int IsNumeric(string input)
{
throw new NotImplementedException(); // this won't get called
}
}
Now, of course, if you want to involve the Canadian codes in the search (e.g. >= 'H0H 0H0'), then you have a whole new problem, which I don't see any obvious answer to, but if you can limit yourself to segmenting just by the first character (i.e. >= '20000'), then you could do something like this:
from e in DbContext.Regions
where e.EndZip[0] >= '2'
select e;
Using string.CompareTo does work, at least with the setup I used (Linq v4.0.30319, Microsoft SQL Server Standard v12.0.5540, Entity Framework v6.1.3):
from e in DbContext.Regions
where e.EndZip.CompareTo("12345") <= 0
select e
However, in my experience, it only works if you use CompareTo with the entire field (at least, it doesn't work together with SubString).
Therefore, this method will not work with British zip codes.
I have the following query:
var vendors = (from pp in this.ProductPricings
join pic in this.ProductItemCompanies
on pp.CompanyId equals pic.CompanyId into left
from pic in left.DefaultIfEmpty()
orderby pp.EffectiveDate descending
group pp by new { pp.Company, SortOrder = (pic != null) ? pic.SortOrder : short.MinValue } into v
select v).OrderBy(z => z.Key.SortOrder);
Does anyone know how the last OrderBy() is applied? Does that become part of the SQL query, or are all the results loaded in to memory and then passed to OrderBy()?
And if it's the second case, is there any way to make it all one query? I only need the first item and it would be very inefficent to return all the results.
Well it will try to apply the OrderBy to the original query since you are still using an IQueryable - meaning it hasn't been converted to an IEnumerable or hydrated to a collection using ToList or an equivalent.
Whether it can or not depends on the complexity of the resulting query. You'd have to try it to find out. My guess is it will turn the main query into a subquery and layer on a "SELECT * FROM (...) ORDER BY SortOrder" outer query.
Given your specific example the order by in this situation most, likely be appliead as part of the expression tree when it getting build, there for it will be applied to sql generated by the LINQ query, if you would convert it to Enumarable like ToList as mentioned in another answer then Order by would be applied as an extension to Enumerable.
Might use readable code, because as you write it is not understandable.
You will have a problem in the future with the linq statement. The problem is that if your statement does not return any value the value will be null and whenever you make cause a exception.
You must be careful.
I recommend you to do everything separately to understand the code friend.
I recently found out that i cannot call any methods from within a linq query. I am trying to write a query that, on the where clause compares two byte arrays. The value on the database is a GUID of type Raw(32) and it is returned as a byte array. This is the record ID for this table. I need to compare it to another byte array. the second byte array could be converted to a string but since i cannot call methods from within linq i was unable to compare.
I tied a custom "Compare" method, i also wrote an extension method. All received an error indicating "LINQ to Entities does not recognize the method"
Here is the code for what i am trying to do. The where clause causes this error:
LINQ to Entities does not recognize the method 'Boolean SequenceEqual[Byte] (System.Collections.Generic.IEnumerable1[System.Byte], System.Collections.Generic.IEnumerable1[System.Byte])' method, and this method cannot be translated into a store expression."
EPSGEntities dbContex = new EPSGEntities();
byte[] byteArray = ParseHex(ViewState["itemID"].ToString());
var q = (from d in dbContex.EPSG_VSOREJECTS
where d.SDSRECID.SequenceEqual(byteArray)
select d).First();
What version of EntityFramework are you using? On EF6 I am able to simply do the following against a SQL 2012 table with a varbinary column:
var q = dbContext.EPSG_VSOREJECTS.FirstOrDefault(e => e.SDSRECID == byteArray);
Is the SDSRECID property on EPSGEntities of type byte[]?
The alternative here would be to go to straight Sql to get your object. Something like:
dbContext.Database.SqlQuery<EPSG_VSOREJECT>("SELECT TOP 1 *" +
"FROM dbo.EPSGEntities" +
"WHERE SDSRECID = #byteString",
new SqlParameter
{
ParameterName = "byteString",
Value = ViewState["itemID"].ToString(),
}).FirstOrDefault();
Linq to Entities in EF is awesome for most queries, but I sometimes drop into sql when I need to do something unsupported, complex, or just fast. Hope this helps!
I'm not entirely sure this works, but I've found calling .AsEnumerable() on the IQueryable object set lets me apply pretty much any code I wish:
var q = dbContex.EPSG_VSOREJECTS.
.AsEnumerable()
.Where(d => d.SDSRECID.SequenceEqual(byteArray));
Doing so seems to prevent EF from trying to translate the Where() clause into SQL syntax, but I have no real idea what the performance hit would/will be.
This is also using method syntax, since I'm not real familiar with query syntax. HTH.
EDIT:
As some others have noted, you have to be careful with how you add any of the iterative methods (AsEnumerable(), ToList(), etc.) since past that point you are no longer building SQL against your data store. Once you start iterating, EF will execute whatever query has been built up to that point, and from then on you are filtering the result set from the LINQ query.
In this case, I don't know that this can be avoided, unless someone can build the same query as a sproc (which EF can execute on your behalf).
I have this method:
public virtual IEnumerable<Invoice> GetHomePageInvoices(IList<Area> areas, FinancialYearLookup financialYear)
{
var homePageInvoices = _db.Invoices.Where(x => areas.Any(z => z.Id == 3)).ToList();
...
}
Basically I'm trying to find any invoices where the area matches with any of those in the parameter area.
I'm getting the error:
Unable to create a constant value of type 'Models.Area'. Only
primitive types ('such as Int32, String, and Guid') are supported in
this context.
Can anyone explain why this is happening and how to fix?
You cannot use an IList<Area> in the context of your Linq Provider (presumably Linq to Entities) - just extract the id's beforehand and use a Contains query which does work on a collection of primitives:
List<int> ids = areas.Select( x=> x.Id).ToList();
var homePageInvoices = _db.Invoices
.Where(x => ids.Contains(x.Id))
.ToList();
Also I assume you did not want to compare with a fixed value of 3 - so I changed your query accordingly - provided the Invoice entity has an Id property.
a. It looks like you have a typo here:
z => z.Id == 3
but the main problem is
b. I'm guessing you're using Linq to Entities but its not clear. In any case what is happening is that the query builder is trying to turn that 'areas.Any(...)' into SQL and it can't do it because areas is not an IQueryable from your database, but a local variable. I suggest you use something like this WhereIn custom Linq operator as described here or here. That will build a SQL in clause containing all the items in areas that you might want to match against.