EF与Web API中多对多关系中间表自动填充修复咨询
问题:EF多对多关系中新增电影时中间表未自动写入关联数据
我通过Entity Framework配置了Customer与Movie实体的多对多关系,EF已自动生成包含CustomerId和MovieId双主键的CustomerMovie中间表。但实现AddMovie接口新增电影时,中间表未自动填入添加该电影的CustomerId与对应的MovieId,不确定是接口实现还是关系配置存在问题。
接口实现代码
[HttpPost("AddMovie"), Authorize] public ActionResult<Movie> AddMovie([FromBody] MovieDto movie) { if (movie == null || !ModelState.IsValid) { return BadRequest(ModelState); } if (_movieRepository.CheckMovieByTitle(movie.Title)) { ModelState.AddModelError("", "Movie Already exists, if both share the same name add the release year with the name"); return StatusCode(422, ModelState); } var userEmail = User.FindFirstValue(ClaimTypes.Email); Customer customerAdded = _customerRepository.GetCustomerByEmail(userEmail); Movie addedMovie = _movieRepository.AddMovie(movie, userEmail, customerAdded); return Ok(addedMovie); }
仓储类代码
public Movie AddMovie(MovieDto movie, string email, Customer customerAdded) { Movie newMovie = new Movie { Title = movie.Title, Description = movie.Description, Duration = movie.Duration, ReleaseDate = movie.ReleaseDate, Rating = 0, AddedByUser = email }; _context.Movie.Add(newMovie); Save(); return newMovie; }
DbContext配置代码
public class ClassContextDb : DbContext { public ClassContextDb(DbContextOptions<ClassContextDb> options) : base(options) { } public DbSet<Customer> Customer { get; set; } public DbSet<Movie> Movie { get; set; } public DbSet<Genre> Genre { get; set; } public DbSet<MembershipType> MembershipType { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Customer>() .HasMany(c => c.Movie) .WithMany(m => m.Customer) .UsingEntity(j => j.ToTable("CustomerMovie")); } }
实体模型相关代码
Customer类集合属性
public virtual ICollection<Movie> Movie { get; set; } = new List<Movie>();
Movie类完整代码
public class Movie { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int MovieId { get; set; } [Required] [MaxLength(30)] public string Title { get; set; } [Required] public DateTime ReleaseDate { get; set; } [Required] [Range(0, 10)] public float Rating { get; set; } [Required] [MaxLength(200)] [MinLength(15)] public string Description { get; set; } [Required] public int Duration { get; set; } public string AddedByUser { get; set; } public virtual ICollection<Customer> Customer { get; set; } = new List<Customer>(); public virtual ICollection<Genre> Genre { get; set; } }
解决方案
核心问题
EF不会自动为新创建的Movie和当前Customer建立关联,必须手动将两者加入对方的关联集合中,EF才会在保存时自动写入中间表数据。
修改仓储类代码
在创建新Movie后,将当前Customer添加到Movie的关联集合,或者将Movie添加到Customer的关联集合,示例如下:
public Movie AddMovie(MovieDto movie, string email, Customer customerAdded) { Movie newMovie = new Movie { Title = movie.Title, Description = movie.Description, Duration = movie.Duration, ReleaseDate = movie.ReleaseDate, Rating = 0, AddedByUser = email }; // 建立新电影与当前用户的关联 newMovie.Customer.Add(customerAdded); // 或者反过来:customerAdded.Movie.Add(newMovie); _context.Movie.Add(newMovie); Save(); return newMovie; }
额外注意事项
- 确保
customerAdded是被EF上下文跟踪的实体:如果GetCustomerByEmail方法是直接从_context.Customer查询返回的,那它默认是被跟踪的;如果是脱离上下文的对象,需要先调用_context.Customer.Attach(customerAdded)将其附加到上下文。 - 建议将实体中的集合属性命名为复数形式(比如
Movies、Customers),避免与类名混淆,提升代码可读性。
内容的提问来源于stack exchange,提问作者Yazeed Fayoumi
相关产品推荐
相关产品推荐

