Вы можете столкнуться с проблемами, связанными с тегами, если они не являются объектами, связанными с текущим контекстом или запросом.Кроме того, является ли Уведомление новым объектом или представляет запись, которая уже существует в базе данных?Ожидается ли, что контекст узнает об этом?
При поиске связей на основе критериев я обычно выбираю работу с идентификаторами, поскольку это упрощает запрос на совпадения.Например:
public void AddUserNotification(Notification notification, IList<int> tagIds)
{
var usersToAddTheNotificationTo = DbContext.Users
.Where(x => x.Tags.Any(t => tagIds.Contains(t.TagId)).ToList();
foreach(var user in usersToAddTheNotificationTo)
{
user.Notifications.Add(notification);
}
}
Без изменения подписи:
public void AddUserNotification(Notification notification, IList<Tag> tags)
{
var tagIds = tags.Select(x => x.TagId).ToList();
var usersToAddTheNotificationTo = DbContext.Users
.Where(x => x.Tags.Any(t => tagIds.Contains(t.TagId)).ToList();
foreach(var user in usersToAddTheNotificationTo)
{
user.Notifications.Add(notification);
}
}
Еще одно предупреждение: если уведомление представляет существующую запись, вам также следует загрузить ее из контекста на основе идентификатора.
var existingNotification = DbContext.Notifications.Single(x => x.NotificationId == notification.NotificationId);
Объекты, передаваемые в такие вещи, как действия контроллера, десериализованы, так что в отношении DbContext они ничем не отличаются от кода, подобного:
var notification = new Notification { NotificationId = 16, .... };
Неважно, что ранее уведомление загружалось из DbContext.Это был другой экземпляр DbContext, и объект был сериализован и десериализован.EF будет воспринимать это как новую запись.Если PK сконфигурирован как Identity, вы получите новую запись с новым NotificationID.Если PK не настроен, вы получите нарушение ключа, когда EF попытается вставить дублирующую строку.Вы можете связать его с DbContext с помощью Attach()
и установить для состояния «Изменено», но это подвергает вашу систему значительному риску подделки, поскольку клиенты могут изменять эту сущность так, как вы этого не ожидаете, изменяя FK или другие значения, которые вы используете.Пользовательский интерфейс не разрешает и не перезаписывает данные.