简体   繁体   中英

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

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. Ie, 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.

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 - ie you can't navigate from an Email to a User directly, but have to go through the join table to get to them.

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM