Entity Framework relation not loaded from database

ado.net c# database entity-framework entity-framework-6

Question

When using Entity Framework 6 Code First to experiment, I run into the issue of a many-to-many connection that is not properly synced to my "internal" objects.

I took the following classes:

public class ClassA
{
    public String AId { get; set; }
    public ICollection<ClassB> Bs { get; set; }
    public ICollection<ClassC> Cs { get; set; }
}
public class ClassB
{
    public int BId { get; set; }
    ICollection<ClassA> As { get; set; }
}
public class ClassC
{
    public int CId { get; set; }
    public ClassA A { get; set; }
}

In contrast to A and C, who are in a one-to-many connection, A and B are many to many. I create the mappings using Fluent API.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<ClassA>().ToTable("ClassA");
    modelBuilder.Entity<ClassA>().HasKey(a => a.AId);
    modelBuilder.Entity<ClassA>().HasManyClassB>(a => a.Bs).WithMany(b => b.As).Map(
            a =>
            {
                a.MapLeftKey("AId");
                a.MapRightKey("BId");
                a.ToTable("ClassAClassB");
            });

    modelBuilder.Entity<ClassA>().Property(a => a.OrderId).IsVariableLength().HasColumnName("AId");
    modelBuilder.Entity<ClassB>().ToTable("ClassB");
    modelBuilder.Entity<ClassB>().HasKey(b => b.BId);
    modelBuilder.Entity<ClassB>().Property(b => b.BId)
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
         .HasColumnName("BId");
    modelBuilder.Entity<ClassC>().ToTable("ClassC");
    modelBuilder.Entity<ClassC>().HasKey(c => c.CId);
    modelBuilder.Entity<ClassC>().HasRequired(c => c.A).WithMany(a => a.Bs).Map(m => m.MapKey("AId"));
    modelBuilder.Entity<ClassC>().Property(c => c.CId)    
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
         .HasColumnName("CId");
}

Invoking SaveChanges after creating objects of classes ClassA, ClassB, and ClassC in my database context (). The values are, in my view, accurately saved in the database:

MariaDB [Test]> select * from ClassA;
+----------+
|   BId    |
+----------+
| 2017-002 |
+----------+

MariaDB [Test]> select * from ClassB;
+--------+
|   BId  |
+--------+
|    2   |
+--------+

MariaDB [OMSData]> select * from ClassAClassB;
+----------+-----+
|    AId   | BId |
+----------+-----+
| 2017-002 |  2  |
+----------+-----+

MariaDB [Test]> select * from classC;
+----+-----------+
| CId |    AId   |
+-----+----------+
|  1  | 2017-002 |
+-----+----------+

However, the relationships are not successfully restored if I run my test programme again.

This implies:

  • There are no objects in the B's collection in ClassA. (and vice versa).
  • Only if I had already accessed the object of ClassC via my database context could I access it through ClassA.

Is the model definition incorrect, or do I need to manually initiate the synchronisation?

I appreciate it.

1
1
9/3/2017 2:12:35 AM

Accepted Answer

Your class structures are flawed. If you follow logic, you must store your many-to-many bindings someplace, which necessitates the use of a third entity class to hold the many-to-many relations.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

Create your classes as follows:

public class ClassA
{
    [Index(IsUnique = true)]
    [MaxLength(200)]
    public String AId { get; set; }
    public virtual List<AB> AB { get; set; }
    public List<ClassC> C { get; set; }
}
public class ClassB
{
    public int BId { get; set; }
    public virtual List<AB> AB { get; set; }
}
public class AB
{
    public int Id { get; set; }
    [Required]
    public virtual A A { get; set; }
    [Required]
    public virtual B B { get; set; }
    [MaxLength(200)]
    public string AId { get; set; }
    public int BId { get; set; }
}
public class ClassC
{
    public int CId { get; set; }
    public ClassA A { get; set; }
    public int AId { get; set; }
}

Create a code-first migration, and entity framework will take this into account while laying up your database. Just save A and B's IDs in the third entity, AB.

1
9/3/2017 7:50:59 AM

Popular Answer

ZZZ_tmp


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow