none
Declaring Navigation Property in Entity Framework RRS feed

  • Question

  • Hi,

    I developed a sample application in EF which has 3 tables 

    PersonDetails, BankDetails and FixedDepositDetails. Please find the table structure below

    create table PersonDetails
    (PersonId int Primary Key,
    PersonName varchar(30))
    
    create table BankDetails
    (BankId int Primary Key,
    BankName varchar(100),
    BankBranch varchar(100),
    BankLocation varchar(100))
    
    create table FixedDepositDetails
    (
    Id int Primary Key,
    FixedDepositNo varchar(30) not null,
    Bank_Id int, -- references Bank Details
    Person_Id int, -- references Person Details
    DOD datetime,
    DOM datetime,
    DepositAmount decimal(9,2),
    MaturityAmount decimal(9,2),
    ROI decimal(3,2),
    Period varchar(20),
    Parent_Id int,
    Constraint fk_BankId Foreign Key(Bank_Id) references BankDetails(BankId),
    Constraint fk_PersonId Foreign Key(Person_Id) references PersonDetails(PersonId),
    Constraint fk_ParentId Foreign Key(Parent_Id) references FixedDepositDetails(Id)
    )

    Now in the Entity framework I have specified as given below

    [Serializable] public class PersonDetails { [Key] public int PersonId { get; set; } public String PersonName { get; set; } } [Serializable] public class BankDetails { [Key] public int BankId { get; set; } public String BankName { get; set; } public String BankBranch { get; set; } public String BankLocation { get; set; } } [Serializable] public class FixedDepositDetails { [Key] public int Id { get; set; } public String FixedDepositNo { get; set; } [ForeignKey("Bank_Id")] public int? Bank_Id { get; set; } public BankDetails BankDetails { get; set; } [ForeignKey("Person_Id")] public int? Person_Id { get; set; } public PersonDetails PersonDetails { get; set; } public DateTime DOD { get; set; } public DateTime DOM { get; set; } public decimal DepositAmount { get; set; } public decimal MaturityAmount { get; set; } public decimal ROI { get; set; } public String Period { get; set; } [ForeignKey("Parent_Id")] public int? Parent_Id { get; set; } public FixedDepositDetails FixedDepositDetail { get; set; } }

     public class BaseDBContext : DbContext
        {
            public BaseDBContext(string ConnectionString)
                : base(ConnectionString)
            {
     
            }

            public DbSet<PersonDetails> PersonDetails { get; set; }
            public DbSet<BankDetails> BankDetails { get; set; }
            public DbSet<FixedDepositDetails> FixedDepositDetails { get; set; }

            protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<FixedDepositDetails>()
                    .HasRequired(x => x.BankDetails)
                    .WithMany()
                    .HasForeignKey(y => y.Bank_Id);

                modelBuilder.Entity<FixedDepositDetails>()
                   .HasRequired(x => x.PersonDetails)
                   .WithMany()
                   .HasForeignKey(y => y.Person_Id);

            }
        }


    But when I run the application I get an error as

    The navigation property 'Bank_Id' is not a declared property on type 'FixedDepositDetails'. Verify that it has not been explicitly excluded from the model and that it is a valid navigation property.

    If I am not wrong I think I have made some mistakes when creating the model. Can some some please let me know where I am doing the mistake? If some one is able to provide me with a solution Please explain me as what you are doing and why that solution needs to be done?

    Regards,

    Raghul

    • Moved by Dummy yoyoModerator Monday, November 5, 2012 9:20 AM Move for better support. (From:Visual C# General)
    Friday, November 2, 2012 4:53 PM

Answers

  • You have to define the collection attribute for the child table in the parent class for instance in your example:


    [Serializable] public class PersonDetails { [Key] public int PersonId { get; set; } public String PersonName { get; set; }

    public virtual ICollection<FixedDepositDetails> FixedDepositDetail { get; set; } } [Serializable] public class BankDetails { [Key] public int BankId { get; set; } public String BankName { get; set; } public String BankBranch { get; set; } public String BankLocation { get; set; }

    public virtual ICollection<FixedDepositDetails> FixedDepositDetail { get; set; } } [Serializable] public class FixedDepositDetails { [Key] public int Id { get; set; } public String FixedDepositNo { get; set; } public int? Bank_Id { get; set; } public BankDetails BankDetails { get; set; } public int? Person_Id { get; set; } public PersonDetails PersonDetails { get; set; } public DateTime DOD { get; set; } public DateTime DOM { get; set; } public decimal DepositAmount { get; set; } public decimal MaturityAmount { get; set; } public decimal ROI { get; set; } public String Period { get; set; } public int? Parent_Id { get; set; } public FixedDepositDetails FixedDepositDetail { get; set; } }

     public class BaseDBContext : DbContext
        {
            public BaseDBContext(string ConnectionString)
                : base(ConnectionString)
            {
     
            }

            public DbSet<PersonDetails> PersonDetails { get; set; }
            public DbSet<BankDetails> BankDetails { get; set; }
            public DbSet<FixedDepositDetails> FixedDepositDetails { get; set; }

            protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<FixedDepositDetails>()
                    .HasRequired(x => x.BankDetails)
                    .WithMany()
                    .HasForeignKey(y => y.Bank_Id);

                modelBuilder.Entity<FixedDepositDetails>()
                   .HasRequired(x => x.PersonDetails)
                   .WithMany()
                   .HasForeignKey(y => y.Person_Id);

            }
        }

    Just add the icollection and remove the ForeignKey attribute from fixeddepost

    You can define child and parent table viceversa.

    Thanks,

    KJ

    • Proposed as answer by kj-nap Saturday, November 3, 2012 5:39 AM
    • Marked as answer by Alexander Sun Thursday, November 22, 2012 6:35 AM
    Saturday, November 3, 2012 5:39 AM
  • Thanks Kj,

    Your solution helped me, but I have another solution to the same problem it is just replacing the Foreign key attribute. Please find my solution,

    Replace 

    BankDetails  instead of Bank_Id, PersonDetails instead of Person_Id and FixedDepositDetail    instead of Parent_Id.

    Hope this helps some one.

    • Proposed as answer by Alexander Sun Tuesday, November 6, 2012 2:18 AM
    • Marked as answer by Alexander Sun Thursday, November 22, 2012 6:35 AM
    Monday, November 5, 2012 11:38 AM

All replies

  • You have to define the collection attribute for the child table in the parent class for instance in your example:


    [Serializable] public class PersonDetails { [Key] public int PersonId { get; set; } public String PersonName { get; set; }

    public virtual ICollection<FixedDepositDetails> FixedDepositDetail { get; set; } } [Serializable] public class BankDetails { [Key] public int BankId { get; set; } public String BankName { get; set; } public String BankBranch { get; set; } public String BankLocation { get; set; }

    public virtual ICollection<FixedDepositDetails> FixedDepositDetail { get; set; } } [Serializable] public class FixedDepositDetails { [Key] public int Id { get; set; } public String FixedDepositNo { get; set; } public int? Bank_Id { get; set; } public BankDetails BankDetails { get; set; } public int? Person_Id { get; set; } public PersonDetails PersonDetails { get; set; } public DateTime DOD { get; set; } public DateTime DOM { get; set; } public decimal DepositAmount { get; set; } public decimal MaturityAmount { get; set; } public decimal ROI { get; set; } public String Period { get; set; } public int? Parent_Id { get; set; } public FixedDepositDetails FixedDepositDetail { get; set; } }

     public class BaseDBContext : DbContext
        {
            public BaseDBContext(string ConnectionString)
                : base(ConnectionString)
            {
     
            }

            public DbSet<PersonDetails> PersonDetails { get; set; }
            public DbSet<BankDetails> BankDetails { get; set; }
            public DbSet<FixedDepositDetails> FixedDepositDetails { get; set; }

            protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<FixedDepositDetails>()
                    .HasRequired(x => x.BankDetails)
                    .WithMany()
                    .HasForeignKey(y => y.Bank_Id);

                modelBuilder.Entity<FixedDepositDetails>()
                   .HasRequired(x => x.PersonDetails)
                   .WithMany()
                   .HasForeignKey(y => y.Person_Id);

            }
        }

    Just add the icollection and remove the ForeignKey attribute from fixeddepost

    You can define child and parent table viceversa.

    Thanks,

    KJ

    • Proposed as answer by kj-nap Saturday, November 3, 2012 5:39 AM
    • Marked as answer by Alexander Sun Thursday, November 22, 2012 6:35 AM
    Saturday, November 3, 2012 5:39 AM
  • Thanks Kj,

    Your solution helped me, but I have another solution to the same problem it is just replacing the Foreign key attribute. Please find my solution,

    Replace 

    BankDetails  instead of Bank_Id, PersonDetails instead of Person_Id and FixedDepositDetail    instead of Parent_Id.

    Hope this helps some one.

    • Proposed as answer by Alexander Sun Tuesday, November 6, 2012 2:18 AM
    • Marked as answer by Alexander Sun Thursday, November 22, 2012 6:35 AM
    Monday, November 5, 2012 11:38 AM
  • I know this is an old thread, but when doing it either way you guys described, I get:

    "The foreign key component 'FixedDepositDetail' is not a valid navigation property on type 'PersonDetails'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property."

    I had my own one-to-many relationship, but for the sake of not involving new items, it mirrors this setup from above:

    public class PersonDetails {

    [Key] public int PersonId { get; set; } public String PersonName { get; set; }

    public virtual ICollection<FixedDepositDetails> FixedDepositDetail { get; set; } }

    public class FixedDepositDetails { [Key] public int Id { get; set; }

    public int? Person_Id { get; set; }

    [ForeignKey("Person_Id")] public PersonDetails PersonDetails { get; set; }

    public FixedDepositDetails FixedDepositDetail { get; set; } }

    Any ideas on how this setup should work, or is this what you guys have?

    Wednesday, January 7, 2015 4:15 AM