Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF4 - custom ObjectContext and inheritance question

Spinning further on the previous question I had. Let's say I inherit BlogEntry and Comment from Post. I now want to customize them a bit. A comment to a blog post does not need a title but a comment needs a user reference so I move these two fields out from Post and into Comment and Blog entry like this:

public abstract class Post
{
    public virtual int Id { get; set; }
    public virtual string Text { get; set; }
    public virtual DateTime CreatedAt { get; set; }
}

public class BlogEntry : Post
{
    public virtual string Header { get; set; }
    public virtual Blog Blog { get; set; }
    public virtual IEnumerable<Comment> Comments { get; set; }
}

public class Comment : Post
{
    public virtual string Header { get; set; }
    public virtual int UserId { get; set; }
    public virtual BlogEntry BlogEntry { get; set; }
}

Now I create my custom object context:

public class EntityContext : System.Data.Objects.ObjectContext
{
    public EntityContext() : base("name=Entities", "Entities")
    {
        this.Blogs = CreateObjectSet<Blog>();
        this.Posts = CreateObjectSet<Post>();
        this.Entries = CreateObjectSet<BlogEntry>();
        this.Comments = CreateObjectSet<Comment>(); 
    }
    public ObjectSet<Blog> Blogs { get; set; }
    public ObjectSet<Post> Posts { get; set; }
    public ObjectSet<BlogEntry> Entries { get; set; }
    public ObjectSet<Comment> Comments { get; set; }
}

This gives me the following actually quite descriptive error message:

Test method threw exception: System.ArgumentException: There are no EntitySets defined for the specified entity type 'BlogEntry'. If 'BlogEntry' is a derived type, use the base type instead. For example, you would see this error if you called CreateObjectSet() and DiscontinuedProduct is a known entity type but is not directly mapped to an EntitySet. The DiscontinuedProduct type may be a derived type where the parent type is mapped to the EntitySet or the DiscontinuedProduct type might not be mapped to an EntitySet at all. Parameter name: TEntity

Now I am not a master of inheritance and stuff but the way I see this would be to add a set of Entries and Comments as ObjectSet< Post> that would solve my problems?

like image 884
mhenrixon Avatar asked May 28 '09 21:05

mhenrixon


1 Answers

If you create an ObjectSet for a base type (i.e. Post) you can't create one for derived types too, because you can retrieve instances of all types in the inheritance hierarchy from that one ObjectSet.

i.e. ctx.Posts.OfType<BlogEntry>() would return BlogEntry(s).

So the answer is to simply remove the other two sets.

If yo need to do an add for example you can do this:

ctx.Posts.AddObject(new BlogEntry {....});

no problem at all.

To help you write queries more easily you could probably add a couple of properties to your ObjectContext that look like this:

public ObjectQuery<BlogEntity> Blogs{
   get{
       return ctx.Posts.OfType<BlogEntry>() as ObjectQuery<BlogEntry>;
   }
} 

and the same for comments.

Hope this helps

Alex

like image 109
Alex James Avatar answered Oct 01 '22 17:10

Alex James