Home > Blockchain >  How do I insert into a join table in Entity Framework?
How do I insert into a join table in Entity Framework?

Time:08-24

Good day all,

I am currently busy writing an email management program for our team in the office.

The issue that I am currently facing is inserting into a join table.

The setup is as follows:

  • I have a table called EmailDetails (This is basically all information related to an email)
  • A table called EmailUser (This is a table containing all the users that would be using the app, and also the users that would be a recipient or CC)
  • Lastly, a table called Email_EmailUser (The join table, seeing that EmailUser & EmailDetails have many-to-many relationship)
  • This is a Database-first approach
{
    [Table("EmailDetails")]
    public class EmailDetails
    {

        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Key]
        public long ID { set; get; }
        public string EmailHeading { set; get; }
        public string EmailBody { set; get; }
        public string EmailAttachment { set; get; }
        public string EmailAttachmentType { set; get; }
        public string EmailAttachmentPath { set; get; }
  
        public virtual ICollection<Email_EmailUser> Email_EmailUser { set; get; }

        public EmailDetails()
        {
            this.Email_EmailUser = new HashSet<Email_EmailUser>();
        }

        public EmailDetails(long ID, string emailHeading, string emailBody, string emailAttachment, string emailAttachmentType, string emailAttachmentPath)
        {

            this.Email_EmailUser = new HashSet<Email_EmailUser>();
            this.ID = ID;
            this.EmailHeading = emailHeading;
            this.EmailBody = emailBody;
            this.EmailAttachment = emailAttachment;
            this.EmailAttachmentType = emailAttachmentType;
            this.EmailAttachmentPath = emailAttachmentPath;
        }
    } 
}
{
    [Table("EmailUsers")]
    public class EmailUser : DbContext
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Key]
        public long ID { set; get; }
        public string UserName { set; get; }
        public string UserEmail { set; get; }
        public int isActive { set; get; }

        public EmailUser()
        {
            this.Email_EmailUser = new HashSet<Email_EmailUser>();
        }


        public EmailUser(long id, string name, string email)
        {
            this.Email_EmailUser = new HashSet<Email_EmailUser>();
            this.ID = id;
            this.UserName = name;
            this.UserEmail = email;
            this.isActive = 1;
        }
   
        public virtual ICollection<Email_EmailUser> Email_EmailUser { set; get; }
    }
}
{
    [Table("Email_EmailUser")]
    public class Email_EmailUser
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Key]
        public long ID { set; get; }
        public long EmailID { set; get; }
        public long EmailUserID { set; get;  } 
        public int IsCC { set; get; }

        public EmailUser EmailUser { set; get; }
        public EmailDetails EmailDetails { set; get; }

        public Email_EmailUser()
        {

        }

    }
}

In my controller I am trying to create a new email which a specific user will have access too. I.e., a new email needs to be created, a record then needs to be inserted into Email_EmailDetails with the new email id and also the id of the current user.

My controller:

            long newEmailID = GetNewEmailID();

            try
            {
                using (DatabaseContext db = new DatabaseContext())
                {
                    EmailDetails newEmail = new EmailDetails(newEmailID, emailHeading, emailBody, emailAttachment, emailAttachmentType, emailAttachmentPath);
                    db.EmailDetails.Add(newEmail);
                    db.SaveChanges();

                    Email_EmailUser emailEmailUser = new Email_EmailUser();

                    emailEmailUser.ID = newEmail_EmailUserID;
                    emailEmailUser.EmailID = newEmail.ID;
                    emailEmailUser.EmailUserID = user.ID;
                    emailEmailUser.IsCC = 1;
                    
                    db.Email_EmailUser.Add(emailEmailUser);
                    db.SaveChanges();
                }
                return true;
                //return email_EmailUser;
            }

When running this code I get the following error:

System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.Entity.Core.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Invalid column name 'EmailDetails_ID'.

I am assuming this issue has something to with how the model is setup, however, I've tried multiple suggestions with no luck.

I am still new to C# & EF, so any advice would be appreciated.

CodePudding user response:

If you didn't need to include the IsCC property, you normally configure this in the OnModelCreating override in your instance of DbContext (depending on which version of EF you're using - EFCore 5 should support this properly now):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<EmailDetails>()
    .HasMany(e => e.EmailUsers)
    .WithMany(u => u.EmailDetails)
    .Map(m =>
      {
        m.MapLeftKey("EmailID");
        m.MapRightKey("EmailUserID");
        m.ToTable("Email_EmailUser");
      });
}

For a database I'm running something similar on the join tables don't have a unique ID, I'm just using a compound ID of the two IDs.

However your setup should work for the additional fields - i.e. you can't navigate from an Email to a User directly, but have to go through the join table to get to them.

CodePudding user response:

After a long and tedious search, I came up with something that worked for me. For some reason, it seems that EF did map the keys correctly.

I ended up using a simple data annotation in my class representing my join table and problem solved.

My join now looks like this:

{
    [Table("Email_EmailUser")]
    public class Email_EmailUser
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Key]
        public long ID { set; get; }
        [ForeignKey("EmailDetails")]
        public long EmailID { set; get; }
        [ForeignKey("EmailUser")]
        public long EmailUserID { set; get;  } 
        public int IsCC { set; get; }
        public virtual EmailUser EmailUser { set; get; }
        public virtual EmailDetails EmailDetails { set; get; }

        public Email_EmailUser()
        {

        }

    }
}

Thanks for all your comments and support. I do appreciate all the effort!

  • Related