none
Error with TPH after upgrading to 4.3 RRS feed

  • Question

  • So we have an existing app built with EF 4.1 which uses TPH in this manner:

        public class TPHConfiguration : EntityTypeConfiguration<TPH>     {         public TPHConfiguration()         {             HasKey<Guid>(p => p.TPHId).Property(p => p.TPHId).IsRequired();             Map<Type1>(p => p.Requires("TPHType").HasValue("Type1"));             Map<Type2>(p => p.Requires("TPHType").HasValue("Type2"));         }

    }

    With properties specific to the derived types having their own configuration:

        public class Type1Configuration : EntityTypeConfiguration<Type1>     {         public Type1Configuration()         {             HasRequired<OtherEntity>(p => p.OtherEntity).WithMany(p => p.Type1s);         }     }

    Map was called more than once for type 'Type1' and at least one of the calls didn't specify the target table name.

    Is it no longer allowed to have config files set up like this with 4.3?

    Tuesday, February 14, 2012 11:52 PM

Answers

  • Hi Rick,

    Thanks for your feedback!

    I'd like to share my testing code, hope it can help you out:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration;
    
    namespace TPH
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var db= new MyContext())
                {
                    db.Database.CreateIfNotExists();
                }
            }
        }
        public class Type
        {
            public int ID { get; set; }
        }
        public class Type1:Type
        {
            public OtherEntity  OtherEntity   { get; set; }
            public int EntityID { get; set; }
        }
        public class Type2:Type
        {
    
        }
        public class OtherEntity
        {
            public int ID { get; set; }
            public ICollection<Type1> Type1s { get; set; }
        }
        public class Type1Configuration : EntityTypeConfiguration<Type1>
        {
            public Type1Configuration()
            {
                Map(p => p.Requires("TPHType").HasValue("Type1"));
                HasRequired(t => t.OtherEntity).WithMany(p => p.Type1s).HasForeignKey(t => t.EntityID);
            }
        }
        public class Type2Configuration : EntityTypeConfiguration<Type2>
        {
            public Type2Configuration()
            {
                Map(p => p.Requires("TPHType").HasValue("Type2"));
            }
        }
        public class MyContext:DbContext
        {
            public DbSet<Type> Types { get; set; }
            public DbSet<OtherEntity> OtherEntities { get; set; }
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Configurations.Add(new Type1Configuration());
                modelBuilder.Configurations.Add(new Type2Configuration());
                //modelBuilder.Entity<Type1>().Map(p => p.Requires("TPHType").HasValue("Type1"));
                //modelBuilder.Entity<Type2>().Map(p => p.Requires("TPHType").HasValue("Type2"));
                //modelBuilder.Entity<Type1>().HasRequired(t => t.OtherEntity).WithMany(p => p.Type1s).HasForeignKey(t=>t.EntityID);
            }
        }
    }
    
    Have a nice day.

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Rick Langel Friday, February 17, 2012 6:38 PM
    Friday, February 17, 2012 6:05 AM
    Moderator

All replies

  • Hi Rick,

    Welcome!

    Thanks for your question, I can repro your scenario too. I'll do some pending research and come back as soon as possible, thanks for understanding.

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, February 15, 2012 5:53 AM
    Moderator
  • Hi Rick,

    In order to fix mapping issue in configuration in EF4.3, the fluent api here should look like:

     protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<type1>().Map(p => p.Requires("TPHType").HasValue("Type1"));
                modelBuilder.Entity<type2>().Map(p => p.Requires("TPHType").HasValue("Type2"));
                modelBuilder.Entity<type1>().HasRequired(t => t.OtherEntity).WithMany(p => p.Type1s).HasForeignKey(t=>t.EntityID);
            }</type1></type2></type1>
    Have a nice day.

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Thursday, February 16, 2012 5:50 AM
    Moderator
  • That doesn't work.  We are using configuration files, not the OnModelCreating method, and we already have that set up as you describe.  We actually already had the foreign key specification included, I just failed to include that in my example.
    Thursday, February 16, 2012 4:44 PM
  • Hi Rick,

    Thanks for your feedback!

    I'd like to share my testing code, hope it can help you out:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration;
    
    namespace TPH
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var db= new MyContext())
                {
                    db.Database.CreateIfNotExists();
                }
            }
        }
        public class Type
        {
            public int ID { get; set; }
        }
        public class Type1:Type
        {
            public OtherEntity  OtherEntity   { get; set; }
            public int EntityID { get; set; }
        }
        public class Type2:Type
        {
    
        }
        public class OtherEntity
        {
            public int ID { get; set; }
            public ICollection<Type1> Type1s { get; set; }
        }
        public class Type1Configuration : EntityTypeConfiguration<Type1>
        {
            public Type1Configuration()
            {
                Map(p => p.Requires("TPHType").HasValue("Type1"));
                HasRequired(t => t.OtherEntity).WithMany(p => p.Type1s).HasForeignKey(t => t.EntityID);
            }
        }
        public class Type2Configuration : EntityTypeConfiguration<Type2>
        {
            public Type2Configuration()
            {
                Map(p => p.Requires("TPHType").HasValue("Type2"));
            }
        }
        public class MyContext:DbContext
        {
            public DbSet<Type> Types { get; set; }
            public DbSet<OtherEntity> OtherEntities { get; set; }
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Configurations.Add(new Type1Configuration());
                modelBuilder.Configurations.Add(new Type2Configuration());
                //modelBuilder.Entity<Type1>().Map(p => p.Requires("TPHType").HasValue("Type1"));
                //modelBuilder.Entity<Type2>().Map(p => p.Requires("TPHType").HasValue("Type2"));
                //modelBuilder.Entity<Type1>().HasRequired(t => t.OtherEntity).WithMany(p => p.Type1s).HasForeignKey(t=>t.EntityID);
            }
        }
    }
    
    Have a nice day.

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Rick Langel Friday, February 17, 2012 6:38 PM
    Friday, February 17, 2012 6:05 AM
    Moderator
  • Thanks, putting the Map method in the inherited class configuration file is different from the examples we'd seen. 

    That did solve the problem!

    Friday, February 17, 2012 6:38 PM