Обновление реляционных объектов

#c# #entity-framework

#c# #entity-framework

Вопрос:

У меня есть сценарий, в котором мне нужна помощь.

Предположим, что есть пользователь, который слушает какой-то тип музыки.

 class User
{   
    public virtual List<UserMusicType> Music { get; set; }
}

public class UserMusicType
{
    public int ID { get; set; }
    public MusicType name { get; set; }
}

public class MusicType
{
    public int ID { get; set; }
    public string Name { get; set; }
}
  

Существует форма, в которой я прошу пользователей проверять / выбирать все типы музыки, которую он слушает. Он выбирает 3 типа, а именно {Поп, рок и электронные}

СЛУЧАЙ 1:

Теперь я хочу обновить объект User и вставить эти 3 новых типа. Насколько я понимаю, мне нужно сначала удалить все музыкальные типы для этих пользователей, которые были сохранены в базе данных, а затем снова вставить эти новые типы. Это правильный подход? Удаление всех предыдущих и вставка новых? Или любой другой способ сделать это?

СЛУЧАЙ 2:

Конечно, я беру имена музыкальных типов в качестве строки. Теперь при обновлении объекта User мне нужно сначала получить MusicType .После этого я смогу это сделать:

 user.Music.Add(new UserMusicType() { ID = SOME_ID });
  

Есть ли лучший подход для этого случая?

Я буду рад получить несколько ответов от опытных людей в EF. Я хочу узнать, есть ли эффективный способ сделать это. Или даже если мой подход / модели совершенно неверны или могут быть улучшены.

Ответ №1:

Прежде всего, вам не нужен UserMusicType класс, вы можете просто объявить `User class как

 class User
{   
    public virtual List<MusicType> Music { get; set; }
}
  

И entity framework создаст таблицу отношений «многие ко многим» в базе данных

Что касается первого вопроса, это зависит. Если вы используете эту связь где-либо еще, например, в журнале платежей или аудита, то лучшим способом было бы сравнить опубликованные значения с сохраненными значениями, например:

Пользователь впервые выбрал музыку 1, музыку 2, музыку 3 и сохранил, в этом случае будут вставлены 3 записи. Пользователь отредактировал свой выбор и выбрал музыку 1, музыку 3, музыку 4, в этом случае вы получите отправленные значения, которые равны 1,3,4, и извлеките значения, хранящиеся в базе данных, которые равны 1,2,3. Затем вы получите новые значения, которые являются элементами, которые существуют в новых значениях, но не в старых, в этом случае это будет 4

Вы получите удаленные значения, которые существуют в старом, но не в новом, в данном случае это будет Music 2. Остальное можно игнорировать.

Итак, ваш запрос будет добавить музыку 4, удалить музыку 2.

Если вы не зависите от отношений, тогда проще просто удалить всю пользовательскую музыку и снова добавить коллекцию.

Что касается второй части вашего вопроса, я предполагаю, что вы отобразите некоторые флажки для пользователя, вы должны указать значение для элемента управления флажком в качестве MusicType идентификатора, и это то, что будет отправлено на серверную часть, и вы можете использовать его, чтобы связать его с пользователем. пример:

 user.Music.Add(new MusicType{ID=[selected ID ]}
  

Вы не должны зависеть от названия музыки

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

1. Хорошо, я не знал, что EF может автоматически создавать таблицы «многие ко многим». Если я использую MusicType. ИДЕНТИФИКАТОР в флажках, любой пользователь может изменить его и ввести некоторый случайный идентификатор, который может никогда не существовать. Будет ли EF добавлять только те, которые существуют? Или он добавит новый идентификатор, как будет? Должен ли я беспокоиться об исключении?

2. Это сделает только пользователь, который имеет очень хорошее знание HTML и некоторый опыт взлома, и вы можете сначала проверить, существует ли идентификатор в вашей базе данных, обратите внимание, что идентификатор не будет виден в пользовательском интерфейсе, типичный HTML для него будет <input type="checkbox" value="1"/> Music 1

Ответ №2:

Первый вопрос:

На самом деле, это личное предпочтение. Потому что не хотелось бы удалять все строки, принадлежащие этому пользователю, а затем вставлять их. Я бы сравнил коллекцию, которая публикуется из формы, со строками, которые хранятся в базе данных. Затем удалите из базы данных те объекты, которые больше не существуют в коллекции. И вставьте новые. Даже вы можете обновить те объекты, которые изменили некоторые дополнительные детали.

Кстати, вы можете легко достичь этого с помощью недавно выпущенного EntityGraphOperations для Entity Framework Code First. Я являюсь автором этого продукта. И я опубликовал его в github, code-project и nuget. С помощью InsertOrUpdateGraph метода он автоматически установит ваши сущности как Added или Modified . И с помощью DeleteMissingEntities метода вы можете удалить те объекты, которые существуют в базе данных, но не в текущей коллекции.

 // This will set the state of the main entity and all of it's navigational 
// properties as `Added` or `Modified`.
context.InsertOrUpdateGraph(user)
       .After(entity =>
       {
            // And this will delete missing UserMusicType objects.
            entity.HasCollection(p => p.Music)
               .DeleteMissingEntities();
       });  
  

Вы можете прочитать мою статью о Code-project с пошаговой демонстрацией, и пример проекта готов к загрузке.

Второй вопрос:

Я не знаю, на какой платформе вы разрабатываете свое приложение. Но, как правило, я храню такие библиотеки как MusicType в кэше. И используйте DropDownList элемент для отображения всех типов. Когда пользователь публикует форму, я получаю значения, а не имена выбранных типов. Таким образом, никакой дополнительной работы не требуется.

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

1. Если я использую MusicType. ИДЕНТИФИКАТОР в флажках, любой пользователь может изменить его и ввести некоторый случайный идентификатор, который может никогда не существовать. Будет ли EF добавлять только те, которые существуют? Или он добавит новый идентификатор, как будет? Должен ли я беспокоиться об исключении?

2. @Waleed Он вставит новые, если вы изменили его состояние на Added . Но, на самом деле, лучший способ — проверить, существует ли уже представленный идентификатор типа в MusicType коллекции, которая хранится в кэше. Итак, никаких дополнительных запросов к базе данных.