You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core多对多关系中Actor与Director记录重复问题求助

问题:创建电影时重复生成演员/导演记录

问题背景

开发了一个展示电影信息的Web API,包含电影及其关联的演员、导演列表。GET接口能正常返回数据,但POST创建电影时,Actor和Director记录会在SQLite数据库中重复创建。业务规则要求:创建电影必须关联演员和导演,但如果演员或导演已存在于数据库中,则无需重复创建。调用POST接口时,客户端提交的DTO不包含ID,需通过Actor.Name和Director.Name属性匹配查找。

模型类定义

Movie类

public sealed class Movie
{
    public int Id { get; init; }
    public string Title { get; init; } 
    public string Synopsys { get; init; }
    public DateOnly ReleaseDate { get; init; }
    public Genre Genre { get; init; }
    public ICollection<Actor> Actors { get; init; }
    public ICollection<Director> Directors { get; init; }
}

Actor类

public sealed class Actor
{
    public int Id { get; init; }
    public string Name { get; init; }
    public DateOnly DateOfBirth { get; init; }
    public string Info { get; set; }
    public ICollection<Movie> Movies { get; set; }
}

Director类

public sealed class Director
{
    public int Id { get; init; }
    public string Name { get; init; }
    public DateOnly DateOfBirth { get; init; }
    public string Info { get; init; }
    public ICollection<Movie> Movies { get; init; }
}

ApplicationDBContext配置

定义DbSet和EF Core多对多关系,会生成Movies、Actors、Directors表以及关联表MovieActors和MovieDirectors:

public class ApplicationDBContext : DbContext
{
    public ApplicationDBContext(DbContextOptions dbContextOptions) 
        : base(dbContextOptions)
    {
         
    }
    public DbSet<Movie> Movies { get; set; }
    public DbSet<Actor> Actors { get; set; }
    public DbSet<Director> Directors { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Movie>()
            .HasMany(a => a.Actors)
            .WithMany(m => m.Movies)
            .UsingEntity(am => am.ToTable("MovieActors"));

        modelBuilder.Entity<Movie>()
            .HasMany(d => d.Directors)
            .WithMany(m => m.Movies)
            .UsingEntity(md => md.ToTable("MovieDirectors"));
    }    
}

原仓储CreateAsync方法

最初的仓储方法会跟踪整个Movie对象并插入所有数据,导致重复创建演员/导演:

public class MovieRepository(ApplicationDBContext context) : IMovieRepository
{
    private readonly ApplicationDBContext context = context;

    public async Task<Movie> CreateAsync(Movie movie)
    {
        context.Movies.Add(movie);
        await context.SaveChangesAsync();
        return movie;
    }
}

API控制器代码

[Route("api/[controller]")]
[ApiController]

// 使用主构造函数
public class MoviesController(IMovieRepository movieRepo) : ControllerBase
{
    private readonly IMovieRepository movieRepo = movieRepo;

    [HttpPost]
    public async Task<IActionResult> CreateMovie([FromBody] CreateMovieDto createMovieDto)
    { 
        var movieModel = createMovieDto.ToMovieFromCreateMovieDto();

        if (await movieRepo.Exists(movieModel.Title))
        { 
            return BadRequest("该电影已存在");
        }
        var movie = await movieRepo.CreateAsync(movieModel);

        return CreatedAtAction(nameof(GetMovieById), new { id = movie.Id }, movie.ToMovieDto());
    }
}

尝试的修改(编辑内容)

尝试修改了CreateAsync方法,先检查数据库中是否存在同名演员/导演,存在则使用已有实体,不存在则添加新实体:

public async Task<Movie> CreateAsync(Movie movie)
{
    var actorsInMovie = movie.Actors;
    movie.Actors = new List<Actor>();

    foreach (var actor in actorsInMovie)
    {
        var actorEntity = await context.Actors.FirstOrDefaultAsync(a => a.Name == actor.Name);

        if (actorEntity is not null)
            movie.Actors.Add(actorEntity);
        else
            movie.Actors.Add(actor);
    }

    var directorsInMovie = movie.Directors;
    movie.Directors = new List<Director>();

    foreach (var director in directorsInMovie)
    {
        var directorEntity = await context.Directors.FirstOrDefaultAsync(d => d.Name == director.Name);

        if (directorEntity is not null)
            movie.Directors.Add(directorEntity);
        else
            movie.Directors.Add(director);
    }

    await context.Movies.AddAsync(movie);
    await context.SaveChangesAsync();
    return movie;
}

内容的提问来源于stack exchange,提问作者Carlos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:45:13