I have recently migrated this code to Entity Framework 4 and it is failing. Obviously if status does not have a value, return all matches, if it does have a value match ones where user.StatusID == 1
.
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
(!status.HasValue || user.StatusID == 1)
);
Exception returned:
ArgumentException: The specified value is not an instance of type 'Edm.Int32'
Parameter name: value
However, removing the conditional test and it works fine:
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
user.StatusID == 1
);
Any ideas? How do you perform conditional testing in EF 4? Surely not separate if lines?
I use these conditional tests time and time again in Linq to Sql; it is really odd as to why this is not functioning in EF 4. There must be something simple going wrong, perhaps there is a recommended alternate way of doing things in EF 4.0.
Thanks for your help guys,
Graham
Ok, I solved it by a combination of two things.
status
variable without the .Value
method.Both must be in place otherwise it will continue to fail with the error! It would have been nice to test the value property, but I guess the query must be really simple - quite interesting!
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
(status == null || user.StatusID == (int) status)
);
I will wait for any better implementation otherwise accept my own answer. But thanks for everybody's help.
How about creating separate variable for !status.HasValue
and using this instead in query?
I think problem here is that EF tries to pass your status variable as parameter into the query and then do the logic in the SQL itself. Try checking what SQL is generated.
An alternative way to doing the null check within the where clause would be to seperate out the optional parameter and only apply it if required.
e.g.
var data = users.Where(
user =>
user.Username == username &&
user.EncryptedPassword == password
);
if (status.HasValue)
{
data = data.Where(user => user.StatusID == status.Value);
}
return data.FirstOrDefault();
I don't think it'll offer much over your current solution other than a little more readability.
Seems like you've already found a solution...
However, just fyi... i have no problem with the following line in VS 2010
Nullable<int> status = 0;
String username = "Alexandre 2";
var test = _context.Contacts.SingleOrDefault(c => c.FirstName == username && (!status.HasValue || c.ContactID == 1));
I get no errors and the Contact object i expect is return ... so if anything, it makes me wonder what is the type of your user.StatusID field?
best of luck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With