none
Unit testing Entity Framework 5.0 DataAccess Layer RRS feed

  • Question

  • Hi everybody,

    I'm trying to write unit tests for my entity framework data access layer and I'm running into some issues.

    Here's my test code

    [TestMethod]
            public void WhenInsertingStudentThenStudentAddedToRepository()
            {               
                Department dept = new Department{Name="Math"};
                provider.GetUnitOfWork.DepartmentRepository.Insert(dept);
                Assert.IsTrue( Provider.GetUnitOfWork.DepartmentRepository.Contains(dept));           
            }

    Where 

    DepartmentRepository.Contains(dept);

    is implemented as follows:

    public virtual bool Contains(TEntity entity) 
    {               
                    return dbSet.Contains<TEntity>(entity);           
    }

    I get the following error message when I run the test


    However, if I implement

    DepartmentRepository.Contains(dept);

    as follows:

    public virtual bool Contains(TEntity entity) 
    {               
                    return dbSet.Local.Contains<TEntity>(entity);           
    }

    Everything works fine. I woull prefer not to use "DBset.Local" directly.

    Can somebody tell me what I'm doing wrong? Thanks for any input.


    • Edited by Amokachi Friday, February 15, 2013 3:17 PM
    Friday, February 15, 2013 3:15 PM

Answers

  • Hi Amokachi,

    When you do dbSet.Contains(...) this is running a query against the database using LINQ to Entity to translate the code you write into a SQL query. The problem is that LINQ to Entities doesn't know how to translate Contains for an entity.

    EF could possibly do this by pulling the primary key values out of the object you provide and adding a where clause to check for the values - but this isn't supported at the moment. You can do this yourself though: dbSet.Where(e => e.Id == entity.Id).Any().

    Local works because the data is already in memory, so your just using LINQ to Objects... which can just check if the exact instance you supplied is in the list.

    BTW it's usually a good idea to avoid hitting the database for unit tests. You can see some patterns for doing this here - http://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/.

    ~Rowan


    We are seeing a lot of great Entity Framework questions (and answers) from the community on Stack Overflow. As a result, our team is going to spend more time reading and answering questions posted on Stack Overflow. We would encourage you to post questions on Stack Overflow using the entity-framework tag. We will also continue to monitor the Entity Framework forum.

    Thursday, February 21, 2013 6:41 PM
    Moderator

All replies

  • Hi Amokachi,

    Welcome to the MSDN forum.

    Starting with .NET Framework 4.5, LINQ to Entities queries are automatically cached. However, LINQ to Entities queries that apply the Enumerable.Contains operator to in-memory collections are not automatically cached. Also parameterizing in-memory collections in compiled LINQ queries is not allowed. Thus you will have to make use of a Contains query with a collection of primitives instead. Please refer to this page: http://msdn.microsoft.com/en-us/library/bb896317.aspx

    If you want to check whether or not an entity is loaded in local, I recommend you check the identity column.

    Best Regards,


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, February 18, 2013 5:37 AM
  • Hi Amokachi,

    When you do dbSet.Contains(...) this is running a query against the database using LINQ to Entity to translate the code you write into a SQL query. The problem is that LINQ to Entities doesn't know how to translate Contains for an entity.

    EF could possibly do this by pulling the primary key values out of the object you provide and adding a where clause to check for the values - but this isn't supported at the moment. You can do this yourself though: dbSet.Where(e => e.Id == entity.Id).Any().

    Local works because the data is already in memory, so your just using LINQ to Objects... which can just check if the exact instance you supplied is in the list.

    BTW it's usually a good idea to avoid hitting the database for unit tests. You can see some patterns for doing this here - http://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/.

    ~Rowan


    We are seeing a lot of great Entity Framework questions (and answers) from the community on Stack Overflow. As a result, our team is going to spend more time reading and answering questions posted on Stack Overflow. We would encourage you to post questions on Stack Overflow using the entity-framework tag. We will also continue to monitor the Entity Framework forum.

    Thursday, February 21, 2013 6:41 PM
    Moderator