locked
How to add 2 foreign keys and their corresponding navigation properties to a model RRS feed

  • Question

  • User-186068080 posted

    Hi all

    I a newcomer in asp.net mvc and i got stuck with a trivial problem for hours. I have a simple class that models a message. its here:

    public class Message
    {
        [Key]
        public int Id { get; set; }
    
        // AspNetUsers
        public ApplicationUser Sender { get; set; }
        public ApplicationUser Receiver { get; set; }
    
        // SenderId of the message
        [Required]
        [ForeignKey("Sender")]
        [Display(Name = "Sender")]
        [InverseProperty("MessageSenderId")]
        public string SenderId { get; set; }
    
        // ReceiverId of this message
        [Required]
        [ForeignKey("Receiver")]
        [Display(Name = "Receiver")]
        [InverseProperty("MessageReceiverId")]
        public string ReceiverId { get; set; }
    
        // other properties
    }

    The SenderId and ReceiverId are the Id of sender and receiver of this message respectively. The Sender and Receiver are navigation properties to fetch them from database when i want to pass the message model to view.

    Unfortunately, when i want to add a new migration, this error is raised: The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.Mails_dbo.AspNetUsers_ReceiverId". The conflict occurred in database "DbName", table "dbo.AspNetUsers", column 'Id'.

    The message class before changing was:

    public class Message
    {
        public int Id { get; set; }
    
        // No Navigation is defined
    
        // SenderId of the message
        [Required]
        [Display(Name = "Sender")]
        public string SenderId { get; set; }
    
        // ReceiverId of this message
        [Required]
        [Display(Name = "Receiver")]
        public string ReceiverId { get; set; }
    
        // other properties
    }

    What can i do? Thanks

    Sunday, February 4, 2018 10:42 AM

Answers

  • User-832373396 posted

    Hi Ehsan,

    How to add 2 foreign keys and their corresponding navigation properties to a model

    Please change a bit to your current code, then it will work.

    Here is the testing working example;

    • 1 find the class ApplicationUser   and add navigation properties ;
       public class ApplicationUser : IdentityUser
        {
            public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
            {
                // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
                var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
                // Add custom user claims here
                return userIdentity;
            }
            [InverseProperty("Sender")]
            public virtual ICollection<Message> SenderMessages { get; set; }
            [InverseProperty("Receiver")]
            public virtual ICollection<Message> ReceiverMessages { get; set; }
        }
    • 2 remove InverseProperty  attribute to SenderId and ReceiverId 
    public class Message
        {
            [Key]
            public int Id { get; set; }
    
            // AspNetUsers
            public virtual ApplicationUser Sender { get; set; }
            public virtual ApplicationUser Receiver { get; set; }
    
            // SenderId of the message
            [Required]
            [ForeignKey("Sender")]
            [Display(Name = "Sender")]
          //  [InverseProperty("MessageSenderId")]
            public string SenderId { get; set; }
    
            // ReceiverId of this message
            [Required]
            [ForeignKey("Receiver")]
            [Display(Name = "Receiver")]
         //   [InverseProperty("MessageReceiverId")]
            public string ReceiverId { get; set; }
    
            // other properties
        }
    • 3 open Package Manager Console and type the command
    PM> Add-Migration ee1
    • 4 find the 201802050240405_ee1.cs file from Migrations folder and change  .ForeignKey("dbo.AspNetUsers", t => t.ReceiverId, cascadeDelete: true)  to  .ForeignKey("dbo.AspNetUsers", t => t.ReceiverId, cascadeDelete: false)
      public partial class ee1 : DbMigration
        {
            public override void Up()
            {
             
                CreateTable(
                    "dbo.Messages",
                    c => new
                        {
                            Id = c.Int(nullable: false, identity: true),
                            SenderId = c.String(nullable: false, maxLength: 128),
                            ReceiverId = c.String(nullable: false, maxLength: 128),
                        })
                    .PrimaryKey(t => t.Id)
                    .ForeignKey("dbo.AspNetUsers", t => t.ReceiverId, cascadeDelete: false)
                    .ForeignKey("dbo.AspNetUsers", t => t.SenderId, cascadeDelete: false)
                    .Index(t => t.SenderId)
                    .Index(t => t.ReceiverId);
                
            }
          ...
        }
    • 5. Ok. Everything is right and we can view the picture;

    Guide

    http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx 

    With regards, Angelina Jolie

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 5, 2018 3:07 AM

All replies

  • User-832373396 posted

    Hi Ehsan,

    How to add 2 foreign keys and their corresponding navigation properties to a model

    Please change a bit to your current code, then it will work.

    Here is the testing working example;

    • 1 find the class ApplicationUser   and add navigation properties ;
       public class ApplicationUser : IdentityUser
        {
            public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
            {
                // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
                var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
                // Add custom user claims here
                return userIdentity;
            }
            [InverseProperty("Sender")]
            public virtual ICollection<Message> SenderMessages { get; set; }
            [InverseProperty("Receiver")]
            public virtual ICollection<Message> ReceiverMessages { get; set; }
        }
    • 2 remove InverseProperty  attribute to SenderId and ReceiverId 
    public class Message
        {
            [Key]
            public int Id { get; set; }
    
            // AspNetUsers
            public virtual ApplicationUser Sender { get; set; }
            public virtual ApplicationUser Receiver { get; set; }
    
            // SenderId of the message
            [Required]
            [ForeignKey("Sender")]
            [Display(Name = "Sender")]
          //  [InverseProperty("MessageSenderId")]
            public string SenderId { get; set; }
    
            // ReceiverId of this message
            [Required]
            [ForeignKey("Receiver")]
            [Display(Name = "Receiver")]
         //   [InverseProperty("MessageReceiverId")]
            public string ReceiverId { get; set; }
    
            // other properties
        }
    • 3 open Package Manager Console and type the command
    PM> Add-Migration ee1
    • 4 find the 201802050240405_ee1.cs file from Migrations folder and change  .ForeignKey("dbo.AspNetUsers", t => t.ReceiverId, cascadeDelete: true)  to  .ForeignKey("dbo.AspNetUsers", t => t.ReceiverId, cascadeDelete: false)
      public partial class ee1 : DbMigration
        {
            public override void Up()
            {
             
                CreateTable(
                    "dbo.Messages",
                    c => new
                        {
                            Id = c.Int(nullable: false, identity: true),
                            SenderId = c.String(nullable: false, maxLength: 128),
                            ReceiverId = c.String(nullable: false, maxLength: 128),
                        })
                    .PrimaryKey(t => t.Id)
                    .ForeignKey("dbo.AspNetUsers", t => t.ReceiverId, cascadeDelete: false)
                    .ForeignKey("dbo.AspNetUsers", t => t.SenderId, cascadeDelete: false)
                    .Index(t => t.SenderId)
                    .Index(t => t.ReceiverId);
                
            }
          ...
        }
    • 5. Ok. Everything is right and we can view the picture;

    Guide

    http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx 

    With regards, Angelina Jolie

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 5, 2018 3:07 AM
  • User-186068080 posted

    Thanks AngelinaJoli for your complete answer.

    But i come to another question. Since i never want to navigate back from user to his mail, does it impose extra load to server?

    Wednesday, February 7, 2018 9:29 AM