none
Code First TPT- Renaming DB ForeignKey That Is Not In Model RRS feed

  • Question

  • I have followed the tutorial on CodeFirst (TPT) located at

    http://weblogs.asp.net/manavi/archive/2010/12/28/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt.aspx

    The tutorial has a User class,a base class called BillingDetail and two subclasses (BankAccount and CreditCard). 
    The inheritance model works fine, but when placing the BillingDetail on User,
    CodeFirst names the User table's BillingDetailId column "BillingDetail_BillingDetailId".
    How can I use the Fluent Api to set the column name to just "BillingDetailId"?

     

    Here is the model used in the tutorial:

     

        public class User
        {
            public int UserId { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public virtual BillingDetail BillingDetail { get; set; }
        }
    
        public abstract class BillingDetail
        {
            public int BillingDetailId { get; set; }
            public string Owner { get; set; }
            public string Number { get; set; }
        }
    
        public class BankAccount : BillingDetail
        {
            public string BankName { get; set; }
            public string Swift { get; set; }
        }
    
        public class CreditCard : BillingDetail
        {
            public int CardType { get; set; }
            public string ExpiryMonth { get; set; }
            public string ExpiryYear { get; set; }
        }

     

    Thanks


    Wednesday, September 21, 2011 5:59 PM

Answers

  • Thanks for your reply. I think I made a mistake in the previous support. I made a test on my side. After you added the following code snippet in the User class as shown here.

        public class User
        {
            public int UserId { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            //It establishes the foreign key relationship between BillingDetails and User, you can check this information from SSMS.
            public virtual BillingDetail BillingInfo { get; set; }
        }
    

    But if you comment this statement, User class was separated from diagram and hasn't any relationship with BillingDetails class. You can also check this information from SSMS. Like the previous code fragment, it generated BillingInfo_BillingDetail column in the User column if you uncomment the previous code. Based on my test, it looks we cannot modify it. I think this behavior was satified with the concept of TPT. I think you can check this blog of first paragraph of Table per Type(TPT).

    Thanks,


    Larcolais Gong[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 Mark Phillips Wednesday, September 28, 2011 5:30 PM
    Wednesday, September 28, 2011 2:13 PM

All replies

  • Hello,

    Thank you for posting.

    From your description, it looks you would like to rename foreign key name. You can check the following code snippets.

    modelBuilder.Entity<Order>() 
        .HasRequired(o => o.Person)
        .WithMany(p => p.Orders)
        .IsIndependent()
        .Map(m => m.MapKey(p => p.PersonId, "CustomFkToPersonId")); 
    

    Please check this blog for more information. http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx

    Thanks,


    Larcolais Gong[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.

    Friday, September 23, 2011 6:15 AM
  • Thanks Larcolais. I had previously seen the snippet you mentioned in your reply.

     Unfortunately, it does not solve the problem. This snippet is expecting a bi-directional navigation. (Order.Person and Person.Orders) The model in my original post has uni-directional navigation. A user can move from User to BillingDetail, but not from BillingDetail to User and the BillingDetailID is not in the User class.


    Friday, September 23, 2011 12:51 PM
  • Hello ,

    First, how to create many-to-many association between two entities? You can code like the following code snippets according to your real scenario.

    HasMany(x => x.SitesFollowing).WithMany(z => z.UserFollowers).Map(y =>  {
                  y.MapLeftKey((x => x.Id), "ID");
                  y.MapRightKey((x => x.Id), "ID");
     });
    
    

    The default mapping convention should be created between PersonID and OrdersID, we didn't need to configure them explicitly.

    Thanks,


    Larcolais Gong[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.

    Monday, September 26, 2011 9:03 AM
  • Thanks for the reply Larcolais. 

    I attempted your suggested solution, but unfortunately the compiler does not like the "WithMany" statement. 

    The model listed in the first post is not a many to many relationship. This model comes from a tutorial on Table Per Type Inheritance. The User has one BillingDetail which is the abstract class that can represent either a CreditCard or BankAccount.  CodeFirst names the foreign key column in the User table "BillingDetail_BillingDetailID."    I'd like to use the Fluent API to set the column to just "BillingDetailID".  The User model does not contain the BillingDetailID property.  Is it possible to do this with the Fluent API?

    Thanks again,
    Mark

     

    Monday, September 26, 2011 1:37 PM
  • Hello Mark,

    I double checked your post, I didn't see any collection was declared in the User class. You should define ICollection<T> in the User class and try it again. In addition, it looks that the relationship of your scenario was a one-to-many. This is the standard one-to-many relationship. Please check it.

    //Standard one to many:
    
    modelBuilder.Entity<Product>() 
        .HasRequired(p => p.PrimaryCategory) 
        .WithMany(c => c.Products) 
        .HasForeignKey(p => p.PrimaryCategoryCode);
    

    Thanks,


    Larcolais Gong[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.

    Tuesday, September 27, 2011 7:24 AM
  • Thanks again Larcolais.

    Yes, the BillingDetail is not a collection.  It is a single reference entity.  The tutorial uses a reference object not a collection.  The goal is to use the polymorphic reference BillingDetail in a Table Per Type inheritance.   EF is able to represent this value as either a BankAccount or a CreditCard.  That part works fine.  The problem is that it is naming the column in the User table, BillingDetail_BillingDetailId.  I wanted to use the FluentAPI to name the column just BillingDetailId.  The User class does not contain a BillingDetailId property.  Maybe EF cannot handle this type of mapping without adding a BillingDetailId property to the User.

    Mark

    Tuesday, September 27, 2011 5:05 PM
  • Thanks for your reply. I think I made a mistake in the previous support. I made a test on my side. After you added the following code snippet in the User class as shown here.

        public class User
        {
            public int UserId { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            //It establishes the foreign key relationship between BillingDetails and User, you can check this information from SSMS.
            public virtual BillingDetail BillingInfo { get; set; }
        }
    

    But if you comment this statement, User class was separated from diagram and hasn't any relationship with BillingDetails class. You can also check this information from SSMS. Like the previous code fragment, it generated BillingInfo_BillingDetail column in the User column if you uncomment the previous code. Based on my test, it looks we cannot modify it. I think this behavior was satified with the concept of TPT. I think you can check this blog of first paragraph of Table per Type(TPT).

    Thanks,


    Larcolais Gong[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 Mark Phillips Wednesday, September 28, 2011 5:30 PM
    Wednesday, September 28, 2011 2:13 PM
  • Larcolais,

    It looks like the tests you made were the same tests that I made. The blog you recommended was the one that was listed in my initial post.

    So if I understand you correctly, the FluentAPI in EF 4.1 cannot change the User column name from BillingDetail_BillingDetailId to BillingDetailId.

    Thanks,
    Mark


    Wednesday, September 28, 2011 5:28 PM