【问题标题】:ef core - how to copy tables from one schema to other with many-to-many relationship?ef core - 如何通过多对多关系将表从一个模式复制到另一个模式?
【发布时间】:2019-06-14 20:45:11
【问题描述】:

我的主架构中有表和映射,我需要在创建另一个架构时重新创建它们。我不知道什么是最好的方法,但现在我这样做了:

            var permissions = context.Permissions.ToList();//master context
            var roles = context.TenantRoles.ToList();

            var permRoles = context.RolePermissions.ToList();
            using (var tenantContext = new TenantContext(newTenant.Id.ToString()))
            {
                RelationalDatabaseCreator creator =
                    (RelationalDatabaseCreator) tenantContext.Database.GetService<IRelationalDatabaseCreator>();
                creator.CreateTables();
                tenantContext.TenantUsers.Add(new TenantUser {UserId = user.Id});
                //tenantContext.Permissions.AddRange(permissions);
                //tenantContext.TenantRoles.AddRange(roles);
                foreach (var role in roles)
                {
                    tenantContext.TenantRoles.Add(new Role {Name = role.Name, CanBeDeleted = role.CanBeDeleted});
                }

                foreach (var permission in permissions)
                {
                    tenantContext.Permissions.Add(new Permission {Name = permission.Name});
                }
                foreach (var map in permRoles)
                {
                    tenantContext.RolePermissions.Add(new RolePermission
                    {
                        Permission = tenantContext.Permissions.FirstOrDefault(p=>p.Name == map.Permission.Name),
                        Role = tenantContext.TenantRoles.FirstOrDefault(r=>r.Name == map.Role.Name)
                    });

                }
                tenantContext.SaveChanges();

            }

SaveChanges() 我得到这个异常:

“实体类型 'RolePermission' 上的属性 'RoleId' 有一个临时值。明确设置一个永久值或确保数据库配置为生成此属性的值。”

如果我手动创建映射(通过创建角色、权限并映射它们的服务),一切正常,所以我猜这不是因为多对多关系。 RolePermissionRolePermission 类是:

public class Permission
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<RolePermission> RolePermissions { get; set; }
}
public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<RolePermission> RolePermissions { get; set; }
    public List<UserRole> UserRoles { get; set; }
    public bool CanBeDeleted { get; set; }
}
public class RolePermission
{
    public int Id { get; set; }
    public int RoleId { get; set; }
    public Role Role { get; set; }
    public int PermissionId { get; set; }
    public Permission Permission { get; set; }
}

OnModelCreating

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema(SchemaName);

        modelBuilder.Entity<TestEntity>().ToTable("TestEntity", SchemaName);
        modelBuilder.Entity<Document>().ToTable("Documents", SchemaName);
        modelBuilder.Entity<Role>().ToTable("Roles", SchemaName);
        modelBuilder.Entity<Permission>().ToTable("Permissions", SchemaName);
        modelBuilder.Entity<TenantUser>().ToTable("TenantUsers", SchemaName);

        modelBuilder.Entity<UserRole>()
            .HasKey(bc => new { bc.RoleId, bc.TenantUserId });
        modelBuilder.Entity<UserRole>()
            .HasOne(bc => bc.Role)
            .WithMany(b => b.UserRoles)
            .HasForeignKey(bc => bc.RoleId);
        modelBuilder.Entity<UserRole>()
            .HasOne(bc => bc.TenantUser)
            .WithMany(c => c.UserRoles)
            .HasForeignKey(bc => bc.TenantUserId);
        modelBuilder.Entity<UserRole>().ToTable("UserRole", SchemaName);

        modelBuilder.Entity<RolePermission>()
            .HasKey(bc => new { bc.RoleId, bc.PermissionId });
        modelBuilder.Entity<RolePermission>()
            .HasOne(bc => bc.Role)
            .WithMany(b => b.RolePermissions)
            .HasForeignKey(bc => bc.RoleId);
        modelBuilder.Entity<RolePermission>()
            .HasOne(bc => bc.Permission)
            .WithMany(c => c.RolePermissions)
            .HasForeignKey(bc => bc.PermissionId);
        modelBuilder.Entity<RolePermission>().ToTable("RolePermissions", SchemaName);

        base.OnModelCreating(modelBuilder);
    }

复制具有关系的表的最佳方法是什么?为什么会出现此错误?

【问题讨论】:

  • 正如异常消息所说:您必须将主键RoleId(和PermissionId)配置为自动生成。 (似乎你没有)。

标签: c# asp.net-core ef-code-first entity-framework-core


【解决方案1】:

您还需要在添加角色和权限后使用tenantContext.SaveChanges()。否则使用EF核心添加RolePermissions时将无法检测到添加的数据。

foreach (var role in roles)
{
    tenantContext.TenantRoles.Add(new Role { Name = role.Name, CanBeDeleted = role.CanBeDeleted });
}
tenantContext.SaveChanges();

foreach (var permission in permissions)
{
    tenantContext.Permissions.Add(new Permission { Name = permission.Name });
}
tenantContext.SaveChanges();

foreach (var map in permRoles)
{
    tenantContext.RolePermissions.Add(new RolePermission
    {
        Permission = tenantContext.Permissions.FirstOrDefault(p => p.Name == map.Permission.Name),
        Role = tenantContext.TenantRoles.FirstOrDefault(r => r.Name == map.Role.Name)
    });

}
tenantContext.SaveChanges();

【讨论】:

  • 不,这不是必需的。 EF 将找出正确的插入顺序并将自动生成的 PK 值复制到 FK。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-13
  • 1970-01-01
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
  • 2016-11-17
相关资源
最近更新 更多