.net 实体框架核心:关系表多对多-插入现有数据

roejwanj  于 2023-10-21  发布在  .NET
关注(0)|答案(2)|浏览(115)

我尝试插入关系数据(有些数据已经存在于我的数据库中)。我怎样才能创作出一首符合我的音乐类型和心情的音乐呢?
我得到这个错误:
Microsoft.EntityFrameworkCore.DbUpdateException:保存实体更改时出错。有关详细信息,请参见内部异常。
异常(0x80004005):23505:重复键值违反唯一约束“PK_Rates”
隐私:由于可能包含敏感数据,因此对详细信息进行了编辑。在连接字符串中指定“包含错误详细信息”以包含此信息。`

实体

AgeRateUpdated
现有数据:

我的代码:

public record Command(CreateMusicRequest Model) : ICommand<Response<CreatedMusicResponse>>;

public class CommandHandler : ICommandHandler<Command, Response<CreatedMusicResponse>>
{
    private readonly IGenericRepository<Music> _musicRepositoryAsync;
    private readonly IGenericRepository<Category> _categoryRepositoryAsync;
    private readonly IGenericRepository<Mood> _moodRepositoryAsync;
    public readonly IGenericRepository<AgeRate> _ageRateRepositoryAsync;
    private readonly IUnitOfWork _unitOfWork;

    public CommandHandler(IGenericRepository<Music> musicRepositoryAsync,
          IGenericRepository<Category> categoryRepositoryAsync, 
          IGenericRepository<Mood> moodRepositoryAsync,
          IGenericRepository<AgeRate> ageRateRepositoryAsync,
          IUnitOfWork unitOfWork)
    {
        _musicRepositoryAsync = musicRepositoryAsync;
        _categoryRepositoryAsync = categoryRepositoryAsync;
        _moodRepositoryAsync = moodRepositoryAsync;
        _unitOfWork = unitOfWork;
        _ageRateRepositoryAsync = ageRateRepositoryAsync;
    }

    public async Task<Response<CreatedMusicResponse>> Handle(Command request, CancellationToken cancellationToken)
    {
        Music music = new()
              {
                  Name = request.Model.Name,
                  ImageUrl = request.Model.ImageUrl,
                  IsUsable = request.Model.IsUsable,
                  Lyrics=request.Model.Lyrics
              };

        music.AgeRate = await _ageRateRepositoryAsync.GetAsync(x => x.Id == request.Model.AgeRateId);

        foreach (var moodId in request.Model.MoodIds)
        {
            Mood existMood = await _moodRepositoryAsync.GetAsync(x => x.Id == moodId);

            if (existMood != null)
            {
                music.Moods.Add(existMood);
            }
        }

        foreach (var categoryId in request.Model.CategoryIds)
        {
            Category existCategory = await _categoryRepositoryAsync.GetAsync(x => x.Id == categoryId);

            if (existCategory != null)
            {
                music.Categories.Add(existCategory);
            }
       }

       await _musicRepositoryAsync.CreateAsync(music);
       await _unitOfWork.CommitAsync();

       return Response<CreatedMusicResponse>.Success(music.Adapt<CreatedMusicResponse>(), 201);
    }
}

EF Core 7,多对多关系

public class MyDbContext : IdentityDbContext<IdentityUser, IdentityRole, string>
{
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {

    }
    public DbSet<Music> Musics { get; set; }
    public DbSet<AgeRate> AgeRates { get; set; }
    public DbSet<Mood> Moods { get; set; }
    public DbSet<Category> Categories { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Music>().Navigation(m => m.Moods).AutoInclude();
        builder.Entity<Music>().Navigation(c => c.Categories).AutoInclude();
        builder.Entity<Music>().Navigation(c => c.AgeRate).AutoInclude();
        base.OnModelCreating(builder);
    }
}```
b1payxdu

b1payxdu1#

根据文档https://learn.microsoft.com/en-us/ef/core/modeling/relationships/many-to-many#examples,可以简单地以这种方式解释多对多关系
我的样本是简化的

public class Music
{
    …
    public int MusicID { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public virtual ICollection<Category> Categories { get; set; }
    public virtual ICollection<Mood> Moods { get; set; }
    public virtual ICollection<AgeRate> AgeRates { get; set; }
}

在DbContext中不需要自动包含
当需要创建与现有实体的关系时,使用Add

public async Task<Music> ManyToMany()
{
    …
    //get the mood
    ICollection<Mood> moods = new List<Mood> {
    _context.Mood.FirstOrDefault(i => i.MoodID == request.Model.AgeRateId) };
    
    _context.Music.Add(new Music { Name = "MusicMoodName1", Url = "MusicMoodUrl1", Moods = moods });

    //same as category/agerate
    …
    _context.SaveChanges();
    …
}

关系表自动创建,执行时插入成功。

音乐表

MoodMusic表

dzhpxtsq

dzhpxtsq2#

问题已解决:

public async Task<T> GetAsync(Expression<Func<T, bool>> filter)
    {
        return await _dbSet.AsNoTracking().SingleOrDefaultAsync(filter);
    }

我删除了AsNoTracking()并开始工作。

相关问题