Search code examples
c#sql-serverentity-frameworkef-code-firstmany-to-many

How can I configure many-to-many relationship to my own created entity in entity framework


I have some classes:

public class Values : Entity
    {
        [Key]
        public int Values_ID { get; set; }    
        [Required]
        public string Values_Name { get; set; }    
        [Required]
        public int ValuesNumeric { get; set; }    
        public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }
    }

public class GQMetric : Entity
    {
        [Key]
        public int GQMetric_ID { get; set; }

        [Required]
        public string GQMetricName { get; set; }
        [Required]
        public int Importance_ID { get; set; }

        public virtual List<GQMetricsQuestions> GQMetricsQuestions { get; set; }
        public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }

        public virtual ImportanceScale ImportanceScale { get; set; }
    }

I need to create many-to-many relationship to my own created class ValuesMetrics, not to automatically generated table by entity framework. I have tried a lot of solutions here, here and here but none of it did not work. Eventually, I did this:

public class ValuesMetrics : Entity
    {
        public int GQMetric_ID { get; set; }
        public int Value_ID { get; set; }

        public virtual GQMetric GQMetric { get; set; }
        public virtual Values Values { get; set; }
    }

FluentAPI:

modelBuilder.Entity<ValuesMetrics>()
               .HasKey(c => new { c.GQMetric_ID, c.Value_ID });

            modelBuilder.Entity<GQMetricsQuestions>()
               .HasKey(c => new { c.GQMetric_ID, c.Question_ID });

but created table (ValuesMetrics) have an excessive relationship (GQMetrics_GQMetric_ID). I need only two primary keys from Values and GQMetrics tables excessive relationship

Can you advice me how to solve this problem? Thanks for any help!


Solution

  • Applied @Esteban 's solution from the link already referenced by you: Create code first, many to many, with additional fields in association table

    Basically I did the following three changes:

    1. Used POCO entities instead of inheriting from Entity class
    2. Removed EF attributes, since we'll be using fluent API anyway
    3. Changed fluent API configuration

    Resulting code:

    public class MyContext : DbContext
    {
        public DbSet<Values> Values { get; set; }
        public DbSet<GQMetric> GqMetric { get; set; }
        public DbSet<ValuesMetrics> ValuesMetrics { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Values>().HasKey(values => values.Values_ID);
            modelBuilder.Entity<GQMetric>().HasKey(metric => metric.GQMetric_ID);
    
            modelBuilder
                .Entity<ValuesMetrics>()
                .HasKey(valuesMetrics => new
                {
                    valuesMetrics.Value_ID,
                    valuesMetrics.GQMetric_ID
                });
    
            modelBuilder
                .Entity<ValuesMetrics>()
                .HasRequired(valuesMetrics => valuesMetrics.Values)
                .WithMany(valueMetrics => valueMetrics.ValuesMetrics)
                .HasForeignKey(valueMetrics => valueMetrics.Value_ID);
    
            modelBuilder
                .Entity<ValuesMetrics>()
                .HasRequired(valuesMetrics => valuesMetrics.GQMetric)
                .WithMany(valueMetrics => valueMetrics.ValuesMetrics)
                .HasForeignKey(valueMetrics => valueMetrics.GQMetric_ID);
    
            base.OnModelCreating(modelBuilder);
        }
    }
    
    public class Values
    {
        public int Values_ID { get; set; }
        public string Values_Name { get; set; }
        public int ValuesNumeric { get; set; }
        public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }
    }
    
    public class GQMetric
    {
        public int GQMetric_ID { get; set; }
        public string GQMetricName { get; set; }
    
        public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }
    }
    
    public class ValuesMetrics
    {
        public int GQMetric_ID { get; set; }
        public int Value_ID { get; set; }
    
        public virtual GQMetric GQMetric { get; set; }
        public virtual Values Values { get; set; }
    }