amaters
amaters

Reputation: 2316

Get a list of multiple types using Entity Framework

Using MVC4 with Entoty Framework CodeFirst I am having problems with the following scenario:

public class Survey
{

    public QuestionCollection Questions {get;set;}
}

public class QuestionCollection : List<IQuestion> //Just for MVC
{ }

public class QuestionType1 : IQuestion { ... }
public class QuestionType2 : IQuestion { ... }

Seems straightforward. Now in my controller I want to get the Survey so i have:

DataContext context = new DataContext ();

var survey = context.Surveys.Include(s => s.Questions).SingleOrDefault(s => s.Id == id);

It does compile but runtime it gives me the error:

A specified Include path is not valid. The EntityType 'Survey' does not declare a navigation property with the name 'Questions'.

What am I doing wrong here? Is there any good tutorial on this topic?

Upvotes: 0

Views: 263

Answers (2)

Leniency
Leniency

Reputation: 5024

Entity Framework Code First requires that navigation collections be declared as an ICollection<T>. Also, to enable lazy loading of the associations, it should be virtual. This is because, unless otherwise specified, EF will return a proxy object wrapping your declared class. Since your original QuestionCollection property is a concrete implementation, it can't override that in the proxy and enable the navigation. Questions has to be declared as the interface.

Your concerns and requirements in EF are different than in MVC, and they aren't always compatible. If you really, really wanted QuestionCollection, you'll have to map that.

Your Surveys entity should look like this:

public class Survey
{
    public virtual ICollection<Question> Questions { get; set; }
}

Also, EF can't implement entity types declared as an interface. This won't work: public virtual ICollection<IQuestion> - your individual question types must all inheirit from a common abstract or concrete instance. They can still implement the interface, but your entity type properties cannot be declared that way.

I would highly recommend going through this series of blog posts on inheritance structures in EF.

The way you would set up your questions entities would look like this:

// You can still keep the IQuestion interface around for MVC
public abstract class Question : IQuestion
{
    // ... properties ...
}

public class QuestionType1 : Question
{
    // ... properties ...
}

public class QuestionType2 : Question
{
    // ... properties ...
}

public class Survey
{
    // Note, collection of Question, not the interface.
    public virtual ICollection<Question> Questions { get; set; }
}

Depending on how exactly you want your table structure to look, the base Question class may or may not be abstract. Refer to the above blog posts to see the various options - Table per Type, Table per Hierarchy, Table per Concrete.

Upvotes: 1

sagar
sagar

Reputation: 177

Have a look at this link,I think you need to set some auto policies http://forums.asp.net/t/1816051.aspx/1

Upvotes: 0

Related Questions