无法使用 DbContext 实体框架核心 SaveChanges()

Posted

技术标签:

【中文标题】无法使用 DbContext 实体框架核心 SaveChanges()【英文标题】:Cannot SaveChanges() with DbContext Entity Framework Core 【发布时间】:2020-10-15 08:37:24 【问题描述】:

我对 EF 核心比较陌生,所以对我来说很简单。

我正在尝试使用 Entity Framework Core 使用数据库优先方法(因为代码优先也不起作用)创建应用程序。我已经成功地使用 EF Core 对所有模型进行了逆向工程,但是在尝试使用我的 DbContext 向数据库添加新项目时,我收到了一个视图嵌套异常消息。我的应用程序使用了两个多对多关系。

我能够将单数项添加到数据库中,问题在于将项添加到联结表中

错误发生在

ctx.Usergorups.Add(newusergroup)

ctx.SaveChanges();

以及所有以下Add() 声明:

Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure.Instance '((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure)ctx.Usergroups).Instance' 引发了“System.NotImplementedException”类型的异常 System.IServiceProvider System.NotImplementedException

发生错误的地方:

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());
        
    

我的DbContext 班级:

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);

【问题讨论】:

如果您使用的构造函数不加载选项,您的数据库上下文如何加载? 我应该删除空的构造函数吗?我的印象是基类负责配置并实例化配置。 @劳伦斯约翰逊 好吧,除非有一些我不知道的魔法,否则不会调用您的基本构造函数。您需要使用传入选项的其他构造函数。我对此不是 100% 确定的唯一原因(以及我问的原因)是因为我使用单例方法。不过,我在 MSDN 文档中没有看到像您这样的方法。所以,如果是我,是的,我会放弃那个构造函数来开始。 @LawrenceJohnson 我认为您正在做某事。在不同的线程中使用相同的 DbContext 似乎是一个依赖注入问题。如果我找到解决方案,我会发布我的解决方案。我将尝试进行适当的依赖管理。 【参考方案1】:

我终于想通了(8 小时后)。这不是依赖注入问题,而是 ID 分配错误。我分配了用户、用户组、访问组和用户组的 ID,并分配了对象,因此从默认构造函数中将 id 设为 0。

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());
                
            

        

【讨论】:

以上是关于无法使用 DbContext 实体框架核心 SaveChanges()的主要内容,如果未能解决你的问题,请参考以下文章

实体框架核心 DbContext 和依赖注入

如何从 DBContext(实体框架核心)中的 App.config(不是 .net 核心应用程序)读取值

实体框架 MySQL DbContext 无法连接

应用程序中断访问 dbcontext、Asp .net 核心 web api 2.0 与实体框架核心 2.0 数据库第一种方法

由于 dotnet ef dbcontext --json 失败,无法在 Visual Studio 2019 中列出实体框架迁移

实体框架核心和多线程