Entity Framework добавление / обновление отношений «многие ко многим»

#c# #asp.net #asp.net-mvc #entity-framework #ado.net

#c# #asp.net #asp.net-mvc #entity-framework #ado.net

Вопрос:

У меня есть две сущности, и когда я обновляю или добавляю только одну, все в порядке

         db.Entry(user1).State = EntityState.Modified;
        foreach (var userAudio in user1.Audios)
        {
            db.Audios.AddOrUpdate(userAudio);
        }
        db.Users.AddOrUpdate(user1);
        db.SaveChanges();
  

Но если я попытаюсь добавить / обновить несколько объектов:

         db.Entry(user1).State = EntityState.Modified;
        foreach (var userAudio in user1.Audios)
        {
            db.Audios.AddOrUpdate(userAudio);
        }
        db.Users.AddOrUpdate(user1);
        db.Entry(user2).State = EntityState.Modified;
        foreach (var userAudio in user2.Audios)
        {
            db.Audios.AddOrUpdate(userAudio);
        }
        db.Users.AddOrUpdate(user2);
        db.SaveChanges();
  

Это вызывает исключение:

Прикрепление объекта типа ‘EfTest.Entities.Сбой «Audio» произошел из-за того, что другой объект того же типа уже имеет то же значение первичного ключа…

Может быть, это потому, что у меня одинаковые аудиозаписи в user1 и user2, и EF не может их вставить…У кого-нибудь есть идеи, как обойти это? Спасибо!

Сущности

 namespace EfTest.Entities
{
    public class User
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public List<Audio> Audios { get; set; }
    }
    public class Audio
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }
        public string Artist { get; set; }
        public string Title { get; set; }
        public List<User> Users { get; set; }
    }
}
  

Комментарии:

1. @Antonio это не работает =(

2. а если вы измените общедоступный список <Audio> Audios { get; set; } на общедоступный ICollection<Audio> Audios {get;set;} и то же самое в ICollection<User>Users {get;set;}?? и обновить базу данных. Запись (пользователь).Текущие значения. setValues(измененные пользователем);

3. @Antonio В любом случае я думаю, что проблема в тех же аудиозаписях, потому что, если я их удалю, все будет работать правильно

4. После каждого db.Users. AddOrUpdate(); используйте db.SaveChanges();

5. @AnilPanwar не работает (

Ответ №1:

К сожалению, я вижу только один способ решить эту проблему. Он добавляет сущности независимо, а затем добавляет отношения:

 var userAudios = new List<Audio>();
// Key userId
// Value list of audiosIds
var userAudiosRelations = new List<Relation>();
foreach (var user in users)
{

    foreach (var audio in user.Audios)
    {
        if (!userAudios.Any(x => x.Id == audio.Id))
        {
            userAudios.Add(audio);
        }
        userAudiosRelations.Add(new Relation
        {
            User_Id = user.Id,
            Audio_Id = audio.Id
        });
    }
    user.Audios = null;
    db.Users.AddOrUpdate(user);
}
foreach (var audio in userAudios)
{
    db.Audios.AddOrUpdate(audio);
}
db.SaveChanges();

var existingRelations = db.Database.SqlQuery<Relation>("SELECT * FROM dbo.UserAudios").ToList();
var relationsToAdd =
    userAudiosRelations.Where(
        x => existingRelations.All(y => x.User_Id != y.User_Id || x.Audio_Id != y.Audio_Id)).ToList();

foreach (var relation in relationsToAdd)
{
    db.Database.ExecuteSqlCommand("INSERT INTO dbo.UserAudios (User_Id, Audio_Id) VALUES (@p0, @p1)",
        relation.User_Id, relation.Audio_Id);
}
  

Где модель отношений:

 public class Relation
{
    public int User_Id { get; set; }
    public int Audio_Id { get; set; }
}