Как работать с вторичными ключами в сущностях самоконтроля? - PullRequest
1 голос
/ 31 августа 2010

Я пытаюсь установить хорошую практику для работы с вторичными ключами при использовании сущностей с самопроверкой и структурой сущностей 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 не допускает, чтобы и оригинальное, и новое значение были одной и той же сущностью (почемуне могу справиться с этим, не имеет для меня ясного смысла).

...