TDD And CodeFirst (Entity Framework)

490 views Asked by At

This question is not about how to test the data access, nor the repository. It's about the problem i have when i want to use my POCO classes (that i've made with TDD) in the project. I mean, this is the problem because of the Linq to Entities limitations (or may be my problem about the design of the classes).

The classes i've arrived to through TDD are the next (extremely simplificated, of course):

public class Person{
    public int IdPerson{ get; set; }
    public string Name { get; set; } 
    public int Average { get; set; }
}

public class Course{
    public int IdCourse { get; set;}
    public Person Professor { get; set;}
    public IEnumerable<Person> Staff { get; set;}
    public IEnumerable<Person> Students { get; set;}

    public IEnumerable<Person> GetGreatStudents(){
        return Students.Where(n => n.Average > 8);
    }
}

Pretty simple, right?

So... what's the problem then? Let's see... When i want to retrieve from the database all the data from the courses (the course class has a lot of subcollections in the reality model) applying filters to them, the only way i could do it was like this:

var course = from obj in Courses //Doesn't matter how i get the courses' collection
             select {
                 IdCourse = obj.IdCourse,
                 GreatStudents = obj.GetGreatStudents(), // Here is the problem
                 OtherCollection = obj.OtherCollection.Where(n => n.Active).Select(n => n.Property1)
             }

As you know, it returns an error because of the GetGreatStudents() function:

LINQ to Entities does not recognize the method [...] this method cannot be translated into a store expression.

I mean, i know i could replace the method directly with the .Where(n => n.Average > 8) but it is awful (and in the reality there are a lot of filters), and on that way, what's the point with TDD if i can't use the api i've built and tested?

So, my question is for those who have experience developing with TDD and Entity Framework, how can you achieve the use of the beautiful API you design through TDD when you work with Linq to Entities?

1

There are 1 answers

0
mark_h On

Firstly, I agree that this is a TDD problem (since you run into it when using TDD!)

The problem you are having is that you have not been able to achieve persistence ignorance; your entities are tied to SQL (and therefore I would argue that they are not POCOs strictly speaking because they are tied to a particular framework)

The only solution I found to this problem was to separate the domain model objects from the persistence model objects (i.e. the EF objects) and write a library that was able to map from my domain objects to my persistence objects. This is a lot of work and I would question whether it was worth it for small projects. If you put pragmatism before purism it is far easier (but less satisfying) to simply understand that you cannot do such things in the EF even though you can write unit tests for them.

I found this and this to be helpful, although a little one-sided.

Your question is an old post so if you've found a better way I'd love to hear it.