仅使用一个SaveChanges调用似乎无法更新我的数据库

时间:2020-09-28 16:45:24

标签: c# asp.net-mvc entity-framework

我正在用自己的方法做几件事;就我而言,它们是必需的,但是优化代码并不是此问题的目的。

在这种方法中,我将创建用户,将用户添加到角色,创建目录,并在df=pd.read_json("E:/Data Science/FlipRobo/Assignments/NLP Sept project/Cell_Phones_and_Accessories.json", orient='records',dtype='dict') df.head() 表中创建记录以将用户链接到新目录。

这里有一些数据库操作,所以我想通过只调用一次SaveChanges来尝试减少数据库的负载。

它似乎什么都没做;我没有看到添加新的首长级成员,也没有添加Directorateuser用户。但是,它将创建用户并将其添加到指定的角色。

是否可以通过这种方式在Entity Framework中对数据进行多次更改批处理,还是每次执行添加或更新记录之类的操作时都必须--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-16-bb0b9f3e9bb6> in <module>() ----> 1 df=pd.read_json("E:/Data Science/FlipRobo/Assignments/NLP Sept project/Cell_Phones_and_Accessories.json", orient='records',dtype='dict') 2 df.head() 5 frames /usr/local/lib/python3.6/dist-packages/pandas/io/json/_json.py in _parse_no_numpy(self) 1106 else: 1107 self.obj = DataFrame( -> 1108 loads(json, precise_float=self.precise_float), dtype=None 1109 ) 1110 ValueError: Expected object or value

DirectorateUsers

编辑

这里每个评论都有额外的型号...

await db.SaveChangesAsync()

4 个答案:

答案 0 :(得分:0)

您需要多对多关系。尽管您有一个User表和Directorates表,所以DirectorateUsers表包含User / ApplicationUser和Directorates之间的多对多关系。因此,您必须为多对多关系定制模型。

public class ApplicationUser
{
    public ApplicationUser() 
    {
        this.Directorates = new HashSet<Directorate>();
    }
....
    public virtual ICollection<Directorate> Directorates { get; set; }
}

首长级模型具有

public class Directorate
{
    public Directorate()
    {
        this.Users = new HashSet<ApplicationUser>();
    }
    public virtual ICollection<ApplicationUser> Users{ get; set; }
}

现在DbContext类看起来像...

public class AppDBContext : DBContext
{
    public AppDBContext() : base("DefaultConnectionString")
    {
    }

    public DbSet<ApplicationUser> Users{ get; set; }
    //or public DbSet<User> Users{ get; set; } //if ApplicationUser doesn't work
    public DbSet<Directorate> Directorates{ get; set; }
        
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        //Configure a Many-to-Many Relationship using Fluent API
            modelBuilder.Entity<User>() //or ApplicationUser
            .HasMany<Directorate>(s => s.Directorates)
            .WithMany(c => c.Users)
            .Map(cs =>
                    {
                        cs.MapLeftKey("UserId");
                        cs.MapRightKey("DirectorateId");
                        cs.ToTable("DirectorateUser");
                    });
    }
}

此映射创建了良好的关系。请检查以下链接以了解多对多关系。 https://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx

现在检查您的代码db.SaveChangesAsync();或不等待,只需db.SaveChanges()。 希望它能起作用。记住您必须以正确的方式映射对象。

答案 1 :(得分:0)

我看到,当您创建Directorateate和DirectorateUser时,您正在使用“ user”变量,该变量可能未引用数据库中的那个。

使用以下变量代替“ user”来创建董事会,DirectorateUser可以解决该问题。

var userDb = await _userManager.FindByNameAsync(user.UserName)

答案 2 :(得分:0)

对我来说,问题在于此。

            db.Entry(municipality).State = EntityState.Modified;
            await db.SaveChangesAsync();

这只会启动与市政相关的保存更改。

但是,我认为您应该有这样的东西。

//set all objects that need to be updated in a modified state
                db.Entry(municipality).State = EntityState.Modified;
                db.Entry(directorate).State = EntityState.Modified;
                db.Entry(directorateUser).State = EntityState.Modified;
//finally save all the changes to the database.
                await db.SaveChangesAsync();

这就是我要的方法。

答案 3 :(得分:0)

我看到您正在使用UserManager访问IdentityDbContext。身份框架使用IUserStore的实例将两者粘合在一起。但是,您已经注意到,每个操作都会立即保存更改。

默认实现UserStore已经具有布尔属性AutoSaveChanges,以防止每次操作都进行保存,但是似乎没有明显的方法可以访问此属性。

您可以用自己的实现替换IUserStore服务(根据UserManager's AutoSaveChanges in .NET Core 2.1);

public class CustomUserStore : UserStore<IdentityUser>
{
    public CustomUserStore(ApplicationDbContext context)
        : base(context)
    {
        AutoSaveChanges = false;
    }
}
services.AddScoped<IUserStore<IdentityUser>, CustomUserStore>();

尽管您随后需要确保所有UserManager / SigninManager调用后面都带有另一个显式保存。

或者您可以添加IUserStore作为依赖项,假设它是UserStore的实例,并在方法周围更改AutoSaveChanges值;

private UserStore<IdentityUser, IdentityRole, DbContext> store;
public Controller(IUserStore<IdentityUser> store)
{
    this.store = store as UserStore<IdentityUser, IdentityRole, DbContext>;
}
public async Task<ActionResult> Create(...){
    try{
        store.AutoSaveChanges = false;
        ...
    }finally{
        store.AutoSaveChanges = true;
    }
}

请注意,您需要哪种UserStore通用类型,取决于您使用的IdentityContext通用类型。

相关问题