ef core - how to copy tables from one schema to other with many-to-many relationship?

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

Question

I have tables and mappings in my master schema, and I need to recreate them when I create another schema. I don't know what is the best approach, but now I do it this way:

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

            }

On SaveChanges() I get this exception:

"The property 'RoleId' on entity type 'RolePermission' has a temporary value. Either set a permanent value explicitly or ensure that the database is configured to generate values for this property."

If I create mappings manually(via service that creates roles, permissions and maps them), everything works fine, so I guess it's not because of many-to-many relationship. Role, Permission and RolePermission classes are:

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

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

What is the best way to copy tables with relationships and why I get this error?

1
0
1/21/2019 12:47:19 PM

Popular Answer

You also need to use tenantContext.SaveChanges() after you have added Roles and Permissions.Otherwise the added data will not be detected when you add RolePermissions using EF core.

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();
0
1/22/2019 8:07:45 AM


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