1

I am relatively new to EF core, so bare with me.

I am trying to create an application using the database-first approach (as code first did not work either) using Entity Framework Core. I have reverse engineered all the models using EF Core successfully, but upon trying to add new items to the database using my DbContext, I get a view nested exception message. My application utilizes two many to many relationships.

I am able to add singular items into the database, the problem arises with adding items into junction tables

The error occurs after

ctx.Usergorups.Add(newusergroup)

at

ctx.SaveChanges();

and all following Add() statements:

My debug window where i found the exception

MessageBox output when I print Exception.Data.ToString()

Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.Instance '((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>)ctx.Usergroups).Instance' threw an exception of type 'System.NotImplementedException' System.IServiceProvider {System.NotImplementedException}

Spot where error occurs:

private void Create_Group(object sender, RoutedEventArgs e)
{
    string groupname = this.namebox.Text;

    if (groupname.Equals("Enter user friendly name") || (groupname.Equals("")))
    {
        MessageBox.Show("The group name cannot be the default. Enter something something descriptive");
        return;
    }
    else
    {
        try
        {
            List<UserUserGroup> usergroups = new List<UserUserGroup>();
            List<AccessGroupUserGroup> Accessgroupers = new List<AccessGroupUserGroup>();
            Usergroups newusergroup = new Usergroups()
                {
                    Name = groupname
                };

            var ctx = new FMS_SIRContext();

            ctx.Usergroups.Add(newusergroup);
            ctx.SaveChanges();

            foreach (Users u in this.members.Where(u => u != null))
            {
                usergroups.Add(new UserUserGroup()
                    {
                        UserId = u.Id,
                        User = u,
                        UserGroupId = newusergroup.Id,
                        UserGroup = newusergroup
                    });
            }

            ctx.UserUserGroup.AddRange(usergroups);

            foreach (Accessgroups a in this.acceessGroups.Where(a => a != null))
            {
                Accessgroupers.Add(new AccessGroupUserGroup()
                    {
                        AccessGroup = a,
                        AccessGroupId = a.Id,
                        UserGroup = newusergroup,
                        UserGroupId = newusergroup.Id
                    });
            }

            ctx.AccessGroupUserGroup.AddRange(Accessgroupers);
            ctx.SaveChanges();

            this.Close();
        }
        catch (Exception s)
        {
            MessageBox.Show(s.Data.ToString());
        }
    }
}

My DbContext class:

public partial class FMS_SIRContext : DbContext
{
    public FMS_SIRContext()
    {
    }

    public FMS_SIRContext(DbContextOptions<FMS_SIRContext> options)
        : base(options)
    {
        this.ChangeTracker.LazyLoadingEnabled = false;
    }

    public virtual DbSet<AccessGroupUserGroup> AccessGroupUserGroup { get; set; }
    public virtual DbSet<Accessgroups> Accessgroups { get; set; }
    public virtual DbSet<UserUserGroup> UserUserGroup { get; set; }
    public virtual DbSet<Usergroups> Usergroups { get; set; }
    public virtual DbSet<Users> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer("Data Source=az18w7413;Initial Catalog=****;Persist Security Info=True;User ID=******;Password=******;");
        }
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AccessGroupUserGroup>(entity =>
        {
            entity.HasKey(e => new { e.AccessGroupId, e.UserGroupId });

            entity.ToTable("AccessGroupUserGroup", "asps");
            entity.HasIndex(e => e.UserGroupId);

            entity.Property(e => e.AccessGroupId).HasColumnName("AccessGroupID");
            entity.Property(e => e.UserGroupId).HasColumnName("UserGroupID");

            entity.HasOne(d => d.AccessGroup)
                .WithMany(p => p.AccessGroupUserGroup)
                .HasForeignKey(d => d.AccessGroupId);

            entity.HasOne(d => d.UserGroup)
                .WithMany(p => p.AccessGroupUserGroup)
                .HasForeignKey(d => d.UserGroupId);
        });

        modelBuilder.Entity<Accessgroups>(entity =>
        {
            entity.ToTable("accessgroups", "asps");

            entity.Property(e => e.Id).HasColumnName("ID");
            entity.Property(e => e.Itname).HasColumnName("ITNAME");
            entity.Property(e => e.Name).HasColumnName("NAME");
            entity.Property(e => e.Permission).HasColumnName("PERMISSION");
        });

        modelBuilder.Entity<UserUserGroup>(entity =>
        {
            entity.HasKey(e => new { e.UserId, e.UserGroupId });

            entity.ToTable("UserUserGroup", "asps");
            entity.HasIndex(e => e.UserGroupId);

            entity.Property(e => e.UserId).HasColumnName("UserID");
            entity.Property(e => e.UserGroupId).HasColumnName("UserGroupID");

            entity.HasOne(d => d.UserGroup)
                .WithMany(p => p.UserUserGroup)
                .HasForeignKey(d => d.UserGroupId);

            entity.HasOne(d => d.User)
                .WithMany(p => p.UserUserGroup)
                .HasForeignKey(d => d.UserId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_UserUserGroup_User");
        });

        modelBuilder.Entity<Usergroups>(entity =>
        {
            entity.ToTable("usergroups", "asps");

            entity.Property(e => e.Id).HasColumnName("ID");
            entity.Property(e => e.Name).HasColumnName("NAME");
        });

        modelBuilder.Entity<Users>(entity =>
        {
            entity.ToTable("Users", "asps");

            entity.HasIndex(e => e.Eid)
                .HasName("IX_EID")
                .IsUnique();

            entity.HasIndex(e => e.Id)
                .HasName("IX_ID");

            entity.Property(e => e.Id).HasColumnName("ID");
            entity.Property(e => e.Eid)
                .HasColumnName("EID")
                .HasMaxLength(50);
            entity.Property(e => e.FirstName).HasMaxLength(100);
            entity.Property(e => e.LastName).HasMaxLength(100);
            entity.Property(e => e.LocationId).HasColumnName("LocationID");
            entity.Property(e => e.Mail).HasMaxLength(200);
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
4
  • 1
    How is your database context loading if you are using a constructor that isn't loading the options? Commented Jun 25, 2020 at 0:46
  • Should I remove the empty constructor? I was under the impression that base class takes care of configuration and instantiates the configuration. @LawrenceJohnson Commented Jun 25, 2020 at 14:37
  • 1
    Well, unless there's some magic that I'm unaware of, your base constructor isn't being called. You'd need to use your other constructor that passes in the options. The only reason I'm not 100% sure on that (and why I asked) is because I use the singleton method. I don't see an approach like yours in the MSDN documentation, though. So, if it were me, yes I'd ditch that constructor to start. Commented Jun 25, 2020 at 15:13
  • @LawrenceJohnson I think you are on to something. It appears to be a dependency injection issue with using the same DbContext across different threads. I will post my solution if I ever find one. I am going to attempt to do proper dependency management. Commented Jun 25, 2020 at 17:58

2 Answers 2

1

I finally figured it out (8 hours later). It was not a dependency injection problem, but rather a ID assignment error. I assigned the ID of user, usergroup, accessgroup, and usergroup as well as assigned the objects, therefor making the ids 0 from the default constructor.

private void Create_Group(object sender, RoutedEventArgs e)
        {
            string groupname = this.namebox.Text;
            if (groupname.Equals("Enter user friendly name") || (groupname.Equals("")))
            {
                MessageBox.Show("The group name cannot be the default. Enter something something descriptive");
                return;
            }
            else
            {
                try
                {
                    List<UserUserGroup> usergroups = new List<UserUserGroup>();
                    List<AccessGroupUserGroup> Accessgroupers = new List<AccessGroupUserGroup>();
                    Usergroups newusergroup = new Usergroups()
                    {
                        Name = groupname
                    };
                    FMS_SIRContext ctx = new FMS_SIRContext();
                    ctx.Usergroups.Add(newusergroup);
                    ctx.SaveChanges();
                    foreach (Users u in members.Where(u => u != null))
                    {
                        usergroups.Add(new UserUserGroup()
                        {
                           UserId = u.Id,
                            //User = u,
                            UserGroupId = newusergroup.Id,
                            //UserGroup = newusergroup
                        });
                    }
                    //ctx.Usergroups.Add(newusergroup);
                    ctx.AddRange(usergroups);
                    foreach (Accessgroups a in this.acceessGroups.Where(a => a != null))
                    {
                        Accessgroupers.Add(new AccessGroupUserGroup()
                        {
                            //AccessGroup = a,
                            AccessGroupId = a.Id,
                            //UserGroup = newusergroup,
                            UserGroupId = newusergroup.Id
                        });
                    }
                    ctx.AddRange(Accessgroupers);
                    ctx.SaveChanges();
                    this.Close();
                }
                catch (Exception s)
                {
                    MessageBox.Show(s.Data.ToString());
                }
            }

        }
Sign up to request clarification or add additional context in comments.

Comments

0

I got a very similar error when I was working on a DbContext in EF Core and it was because I did not save my context after adding related data and not saving, which had a domino effect. I had updated two tables and since one was dependent on the other, the save failed. When you have dependent data, you need to add the dependency, save changes, and then add the new dependent data.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.