外键如何引用实体拆分子表上的属性?

问题描述 投票:0回答:1

我正在基于现有的自定义数据库创建一个新的 IdentityDbContext。多年前就决定将自定义属性添加到另一个表 CustomUser 中,而不是向 AspNetUsers 添加自定义属性,以及它自己的标识列 UserId。然后 UserId 用作 CustomUserAccept 的外键,它记录用户何时接受服务条款、cookie 策略等。

public void CreateCustomUser(EntityTypeBuilder<CustomUser> entity)
{
    entity
        .ToTable("AspNetUsers")
        .SplitToTable("CustomUser", CreateCustomUser);

    entity.HasAlternateKey(e => e.UserId);

    entity.HasMany(d => d.Accepts).WithMany()
        .UsingEntity<CustomUserAccept>(
            "CustomUserAccept",
            r => r.HasOne(d => d.Accept).WithMany()
                .HasForeignKey(d => d.AcceptId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_CustomUserAccept_AcceptId"),
            l => l.HasOne(d => d.User).WithMany()
                .HasPrincipalKey(d => d.UserId)
                .HasForeignKey(d => d.UserId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_CustomUserAccept_UserId"),
            CreateCustomUserAccept);
}

public void CreateCustomUser(SplitTableBuilder<CustomUser> entity)
{
    entity.Property(e => e.UserId).UseIdentityColumn();
    entity.Property(e => e.Id).HasColumnName("IdentityId");
    
    entity.Property(e => e.CompanyId);
    entity.Property(e => e.FirstName);
    entity.Property(e => e.LastName);
    entity.Property(e => e.LastLogonDate);
    entity.Property(e => e.PasswordExpirationDate);
    entity.Property(e => e.ChangePassword);
}

public void CreateCustomUserAccept(EntityTypeBuilder<CustomUserAccept> entity)
{
    entity.HasKey(e => new { e.UserId, e.AcceptId });

    entity.ToTable("CustomUserAccept");

    entity.Property(e => e.CreatedDate)
        .HasDefaultValueSql("(getutcdate())")
        .HasColumnType("datetime");
}

我使用 Entity Splitting 将 AspNetUsers 和 SecureUser 合并到一个 SecureUser 模型中。它工作得很好......直到我添加了对 CustomAccept 的多对多引用。

“Microsoft.EntityFrameworkCore.Model.Validation.ForeignKeyPropertiesMappedToUnrelatedTables”:面向“CustomUser”的实体类型“CustomUserAccept (CustomUserAccept)”上的外键 {“UserId”} 无法在数据库中表示。属性 {'UserId'} 未映射到表 'CustomUserAccept',或者主要属性 {'UserId'} 未映射到表 'AspNetUsers'。所有外键属性必须映射到依赖类型映射到的表,并且所有主体属性必须映射到主体类型映射到的单个表。

是否有任何方法可以通过操作元数据或覆盖来解决“主要属性必须映射到单个表”的问题?除了放弃实体拆分之外,我还能做些什么吗?

c# entity-framework-core asp.net-identity .net-8.0 ef-core-8.0
1个回答
0
投票

我对其他想法持开放态度,但是当我翻转

CustomUser
到主表时,它起作用了,我能够登录。

    public void CreateCustomUser(EntityTypeBuilder<CustomUser> entity)
    {
        entity
            .ToTable("CustomUser")
            .SplitToTable("AspNetUsers", CreateCustomUser);

        entity.Property(e => e.Id).HasColumnName("IdentityId");
        entity.HasAlternateKey(e => e.UserId);

        entity.HasMany(d => d.Accepts).WithMany()
            .UsingEntity<CustomUserAccept>(
                "CustomUserAccept",
                r => r.HasOne(d => d.Accept).WithMany()
                    .HasForeignKey(d => d.AcceptId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_CustomUserAccept_AcceptId"),
                l => l.HasOne(d => d.User).WithMany()
                    .HasPrincipalKey(d => d.UserId)
                    .HasForeignKey(d => d.UserId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_CustomUserAccept_UserId"),
                CreateCustomUserAccept);
    }

    public void CreateCustomUser(SplitTableBuilder<CustomUser> entity)
    {
        entity.Property(e => e.Id).HasColumnName("Id");
        entity.Property(e => e.UserName);
        entity.Property(e => e.NormalizedUserName);
        entity.Property(e => e.Email);
        entity.Property(e => e.NormalizedEmail);
        entity.Property(e => e.EmailConfirmed);
        entity.Property(e => e.PasswordHash);
        entity.Property(e => e.SecurityStamp);
        entity.Property(e => e.ConcurrencyStamp);
        entity.Property(e => e.PhoneNumber);
        entity.Property(e => e.PhoneNumberConfirmed);
        entity.Property(e => e.TwoFactorEnabled);
        entity.Property(e => e.LockoutEnd);
        entity.Property(e => e.LockoutEnabled);
        entity.Property(e => e.AccessFailedCount);
    }
© www.soinside.com 2019 - 2024. All rights reserved.