huyrua / efprs

Entity Framework POCO, Repository and Specification Pattern
MIT License
40 stars 18 forks source link

TPH inheritance and method GetAll #1

Open ghost opened 11 years ago

ghost commented 11 years ago

Hi. Thanks for sharing this.

I have a one problem. I'm using Table per Hierarchy (TPH). For example we have a base class:

public abstract class Entity
    {
        public virtual int Id { get; set; }

        public virtual bool IsTransient()
        {
            return Id == default(int);
        }
    }

And base class for several entitites:

public abstract class Event:Entity
    {
        [MaxLength(50)]
        [Required]
        public string Name { get; set; }

        [Required]
        public string Description { get; set; }

        [Required]
        [MaxLength(100)]
        public string ShortDescription { get; set; }

        [Required]
        public DateTime PublishDate { get; set; }

        public int  Duration { get; set; }
    }

public class Film:Event
    {
        public string Director { get; set; }

        public string ActorList { get; set; }

        public override string ToString()
        {
            return Name;
        }
    }

public class Concert:Event
    {
        public string Genre { get; set; }

        public override string ToString()
        {
            return Name;
        }
    }

My context:

 public class MyContext:DbContext
    {
        public MyContext():base(ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString)
        {
        }

        public DbSet<Event> Events { get; set; }

        public virtual void Commit()
        {
            base.SaveChanges();
        }

    }

Next, create context and repository:

var context = new MyContext();
EventRepository repository = new EventRepository(context);
 var films = repository.GetAll<Film>();

But I get exception: the sequence does not have elements. In this code:

string entitySetName = ((IObjectContextAdapter)DbContext).ObjectContext
                                                                     .MetadataWorkspace
                                                                     .GetEntityContainer(((IObjectContextAdapter)DbContext).ObjectContext.DefaultContainerName, DataSpace.CSpace)
                                                                     .BaseEntitySets.First(bes => bes.ElementType.Name == typeof(TEntity).Name).Name;
diegohb commented 11 years ago

About a year ago, I ran into this same issue and I created overloads for most read/query methods to include the base type .. this was a "quick fix", I'd probably try to do it using reflection if I had to do it again.

the main one that must be overloaded and modified is GetQuery.. something like this.. IQueryable GetQuery<TBaseEntity, TEntity>() { return DbContext.Set().OfType(); }