Я пытаюсь установить хорошую практику для работы с вторичными ключами при использовании сущностей с самопроверкой и структурой сущностей 4, но, похоже, есть много подводных камней.
Допустим, у меня есть сущность Alarm,который может иметь навигационное свойство ConfirmingUser для пользователя.Пользователь имеет Id в качестве первичного ключа и «Логин» в качестве вторичного ключа.В какой-то момент в моей системе я назначаю новую сущность пользователя для ConfirmingUser тревоги.На данный момент я знаю только логин (вторичный ключ) пользователя и, допустим, это n-уровневая архитектура, где нецелесообразно искать Id в этой точке.Тревога позже транспортируется на постоянный уровень, который будет пытаться сохранить Тревогу.Теперь самое сложное.Мне нужно определить, существует ли уже ConfirmingUser в базе данных, и предпринять соответствующие действия.
Вот как я это делаю сейчас:
using (var context = new PantoTestEntities())
{
if (alarm.ConfirmingUser != null && alarm.ConfirmingUser.ChangeTracker.State == ObjectState.Added)
{
var userIdQuery = from user in context.Users
where user.Login == alarm.ConfirmingUser.Login
select user.Id;
if (userIdQuery.Any())
{
// Disable cache or ApplyChanges will throw an exception, because the user already exists.
context.Alarms.MergeOption = MergeOption.NoTracking;
alarm.ConfirmingUser.Id = userIdQuery.First();
alarm.ConfirmingUser.MarkAsModified();
}
}
context.Alarms.ApplyChanges(alarm);
context.SaveChanges();
// Accept changes in the full entity graph
alarm.AcceptAllChanges();
}
Этот шаблон выглядит для меня довольно уродливо и неэффективно.Существуют ли более эффективные способы обработки объектов с «внешними» ключами?
Интересный недостаток приведенного выше кода состоит в том, что невозможно заменить ConfirmingUser новым пользователем с тем же логином.Т.е. когда клиентское приложение хочет назначить ConfirmingUser для Alarm, оно должно проверить, был ли ConfirmingUser уже назначен пользователю с тем же свойством Login.Причина этого заключается в том, что ApplyChanges сущностей с самообследованием будет пытаться скопировать как исходного пользователя, так и нового пользователя в контекст EF, но EF не допускает, чтобы и оригинальное, и новое значение были одной и той же сущностью (почемуне могу справиться с этим, не имеет для меня ясного смысла).