7

Can somebody help me resolve this exception:

Test method KravmagaTests.Model.Entities.StudentTest.Create_Valid_Student threw exception: System.NotSupportedException: Unable to create a constant value of type 'Kravmaga.Models.Account'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

I get this when I run this test method:

[TestMethod]
public void Create_Valid_Student()
{
    Student student = new Student()
    {
        Username = "username",
        Firstname = "firstname",
        Surname = "surname",
        Email = "email@gmail.com",
        Password = "password",
    };
    KravmagaContext context = new KravmagaContext();
    context.AddToAccounts(student);
    context.Save();
    bool exists = context.Accounts.Contains(student); // THIS THROWS EXCEPTION
    Assert.IsTrue(exists);
}

Thanks a lot.

Slauma
  • 175,098
  • 59
  • 401
  • 420
Iškuda
  • 635
  • 1
  • 7
  • 13

2 Answers2

9

Change your test method this way:

// ...
context.Save();
int newStudentId = student.Id;
// because the Id generated by the DB is available after SaveChanges

bool exists = context.Accounts.Any(a => a.Id == newStudentId);
Assert.IsTrue(exists);

Contains doesn't work here because it checks if a particular object instance is in the context.Accounts set. Translation of this check into SQL is not supported, only for primitive types (like the exception says). Any just translates the filter expression you specify into SQL and passes it to the database.

Slauma
  • 175,098
  • 59
  • 401
  • 420
  • @Iškuda: BTW, what are you testing there? Is `context` some selfwritten wrapper around an `ObjectContext` or is it directly your derived `ObjectContext`? In the latter case you aren't testing *your* code but Entity Framework itself. If `exists` would ever be `false` and you didn't get an exception from EF before you reach the `Assert` at all, EF would have a terrible bug. – Slauma Sep 11 '11 at 16:38
  • Thanks! Those little differences between what works in Linq to Objects and EF can be a real bear to figure out. – krillgar May 29 '14 at 17:06
  • 1
    @krillgar: Gert Arnold has written a great answer here (http://stackoverflow.com/a/13352779/270591) that lists a lot of the differences. – Slauma May 30 '14 at 12:38
  • That's an amazing list. Thanks so much! – krillgar May 30 '14 at 13:09
0

The Entity Framework is trying to translate the context.Accounts.Contains(student) into an SQL statement (e.g.: "WHERE ... IN (...)"). It cannot translate it into an SQL statement because it only knows how to handle primitive types (int, string...) hence the exception.

You are probably trying to have the EF generate an SQL statement such as:

SELECT * FROM Accounts WHERE Id IN (1, 2, 3, 4, 5)

You can write such a LINQ To Entities statement as follows:

 var studentIds = new int[] { 1, 2, 3, 4, 5 };
 var matches = from account in context.Accounts
               where studentIds.Contains(account.Id) 
               select account;

For more information take a look at the following blog post:

http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx

The blog post I mentioned offers a work around for the .NET 3.5 framework.

Christophe Geers
  • 8,564
  • 3
  • 37
  • 53