C# &ASP.NET Core:自定义 IdentityUser 的外键冲突

C# & ASP.NET Core : foreign key violation for custom IdentityUser

提问人:József Kiss 提问时间:11/18/2023 最后编辑:marc_sJózsef Kiss 更新时间:11/18/2023 访问量:59

问:

我想使用具有附加属性的扩展类:IdentityUser

namespace SpaceShip.Model;

using Microsoft.AspNetCore.Identity;

public class UserEntity : IdentityUser
{
    // Additional properties 
}

在我的模型类中使用其 Id 作为外键:

public class SpaceShip
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string UserId { get; set; }

    // Navigation property
    public UserEntity User { get; set; }
}

我使用两个单独的 s 来区分关注点:DbContext

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {
    }

    public DbSet<SpaceShipModel> SpaceShips { get; set; } 

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        // Configure the relationship between SpaceShip and AspNetUsers (UserEntity)
        builder.Entity<SpaceShipModel>()
            .HasOne<UserEntity>(s => s.User)
            .WithMany()
            .HasForeignKey(s => s.UserId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade); 
    }
} 

public class UserContext : IdentityDbContext<UserEntity>
{
    public UserContext(DbContextOptions<UserContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        // Additional configuration
    }
}

当我尝试创建一个具有有效 :SpaceShipuserId

[ApiController]
[Route("[controller]")]
public class SpaceShipController : ControllerBase
{
    private readonly SpaceShipService _spaceShipService;

    public SpaceShipController(SpaceShipService spaceShipService)
    {
        _spaceShipService = spaceShipService;
    }

    [HttpPost]
    public async Task<IActionResult> Create(string name, string userId)
    {
        await _spaceShipService.CreateSpaceShipAsync(name, userId);
        return Ok(); 
    }
}

我收到此错误:

Microsoft.EntityFrameworkCore.DbUpdateException:保存实体更改时出错。有关详细信息,请参阅内部异常。

Npgsql.PostgresException (0x80004005): 23503:在表“SpaceShips”上插入或更新违反外键约束“FK_SpaceShips_UserEntity_UserId”

详细信息:表“UserEntity”中不存在密钥 (UserId)=(b3a23cba-ad21-4e5a-9b25-8c5e139c67fe)

发生这种情况是因为约束不是指:FK_SpaceShips_UserEntity_UserIdAspNetUsers

-- Constraint: FK_SpaceShips_UserEntity_UserId

-- ALTER TABLE IF EXISTS public."SpaceShips" DROP CONSTRAINT IF EXISTS "FK_SpaceShips_UserEntity_UserId";

ALTER TABLE IF EXISTS public."SpaceShips"
    ADD CONSTRAINT "FK_SpaceShips_UserEntity_UserId" 
        FOREIGN KEY ("UserId")
        REFERENCES public."UserEntity" ("Id") MATCH SIMPLE
            ON UPDATE NO ACTION
            ON DELETE CASCADE;

问题可以通过修改来暂时解决,参考:FK_SpaceShips_UserEntity_UserIdAspNetUsers

-- Constraint: FK_SpaceShips_UserEntity_UserId

-- ALTER TABLE IF EXISTS public."SpaceShips" DROP CONSTRAINT IF EXISTS "FK_SpaceShips_UserEntity_UserId";

ALTER TABLE IF EXISTS public."SpaceShips"
    ADD CONSTRAINT "FK_SpaceShips_UserEntity_UserId" 
        FOREIGN KEY ("UserId")
        REFERENCES public."AspNetUsers" ("Id") MATCH SIMPLE
            ON UPDATE NO ACTION
            ON DELETE CASCADE;

但它应由实体框架配置,后续迁移可能会覆盖它。我不明白为什么默认情况下不引用外键约束。AspNetUsers

C# PostgreSQL 实体框架 核心 ASP.NET 标识

评论


答:

1赞 József Kiss 11/18/2023 #1

仅使用一个数据库上下文解决了该问题:

public class AppDbContext : IdentityDbContext<UserEntity>
{
    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options)
    {
    }

    public DbSet<SpaceShipModel> SpaceShips { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        // Map UserEntity to AspNetUsers table
        builder.Entity<UserEntity>().ToTable("AspNetUsers");

        // Configure the relationship between SpaceShip and UserEntity (AspNetUsers)
        builder.Entity<SpaceShipModel>()
            .HasOne<UserEntity>(s => s.User)
            .WithMany()
            .HasForeignKey(s => s.UserId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);
    }
}

但是,我仍然不清楚如何使用两个单独的上下文。

评论

0赞 Ann L. 11/18/2023
既然实体是相关的,并且必须引用这两个实体才能使模型正常工作,为什么还要使用两个单独的上下文?
0赞 József Kiss 11/18/2023
我认为以这种方式管理我的模型会更容易,并且这是推荐的模式。
0赞 Ann L. 11/18/2023
我不知道这是推荐的模式,尽管我敢肯定这是由于我没有读得足够多。它们是否可能意味着上下文的单独实例,而不是单独的上下文类?