Гидрат связанные объекты - PullRequest
0 голосов
/ 05 января 2012

Я ищу простой способ увлажнить связанный объект.Заметка принадлежит документу, и только владельцы документа могут добавлять заметки, поэтому, когда пользователь пытается редактировать заметку, мне нужно гидрировать связанный документ, чтобы выяснить, есть ли у пользователя доступ к нему.В моем слое Service у меня есть следующее:

public void editNote(Note note)
    {
        // Get the associated Document object (required for validation) and validate.
        int docID = noteRepository.Find(note.NoteID).DocumentID;
        note.Document = documentRepository.Find(docID);

        IDictionary<string, string> errors = note.validate();
        if (errors.Count > 0)
        {
            throw new ValidationException(errors);
        }

        // Update Repository and save.
        noteRepository.InsertOrUpdate(note);
        noteRepository.Save();
    }

Проблема в том, что noteRepository.InsertOrUpdate (note) выдает исключение: «Объект с таким же ключом уже существует в ObjectStateManager.»когда хранилище устанавливает EntityState.Modified.Таким образом, возникает ряд вопросов:

  1. Правильно ли я подхожу к этому, и если да, как мне обойти исключение?
  2. В настоящее время действие редактирования контроллера принимает NoteCreateEditViewModel.Теперь у него есть поле DocumentID, так как это требуется при создании новой заметки, так как нам нужно знать, к какому документу его прикрепить.Но для редактирования я не могу использовать его, поскольку злоумышленник может предоставить DocumentID, к которому у него do есть доступ, и, таким образом, отредактировать примечание, которое ему не принадлежит.Так должны ли быть отдельные viewmodels для создания и редактирования, или я могу просто исключить DocumentID как-то при редактировании?Или есть лучший способ использовать модели представления так, чтобы идентификатор не требовался?
  3. Есть ли лучший способ приблизиться к этому?Я прочитал, что мне просто нужно иметь репозиторий Document в качестве совокупности и потерять репозиторий Note, но я не уверен, поможет ли это / как это поможет.

Я задал похожий вопрос, связанный с этим, но это не так.Очень ясно, поэтому надеюсь, что эта версия позволит кому-то понять и, следовательно, направить меня в правильном направлении.

РЕДАКТИРОВАТЬ

На основе информации, предоставленной Ладиславом Мрнкой, и подробного ответа здесь: Объект с таким же ключом уже существует в ObjectStateManager.ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом , похоже, мой метод репозитория должен быть похож на следующий:

public void InsertOrUpdate(Note note)
    {
        if (note.NoteID == default(int)) {
            // New entity
            context.Notes.Add(note);
        } else {
            // Existing entity
            //context.Entry(note).State = EntityState.Modified;
            context.Entry(oldNote).CurrentValues.SetValues(note);
        }
    }

Но как мне получить oldNote из контекста?Я мог бы вызвать context.Entry (Find (note.NoteID)). CurrentValues.SetValues ​​(примечание), но я представляю здесь потенциальные проблемы?

1 Ответ

0 голосов
/ 05 января 2012

Правильно ли я подхожу к этому, и если да, то как мне обойти это исключение?

Я полагаю, эта часть вашего кода загружает весь узел из базы данных, чтобы найти DocumentID:

int docID = noteRepository.Find(note.NoteID).DocumentID;

В таком случае ваш InsertOrUpdate не может взять ваш узел и присоединить его к контексту с измененным состоянием, потому что у вас уже есть заметка с тем же ключом в контексте. Распространенным решением является использование этого:

objectContext.NoteSet.ApplyCurrentValues(note);
objectContext.SaveChanges();

Но для редактирования я не могу использовать его, поскольку злоумышленник может предоставить DocumentID, к которому у него есть доступ, и, таким образом, отредактировать заметку, которой он не владеет.

В таком случае вы должны добавить некоторую безопасность. Вы можете добавить любые данные в скрытые поля на своей странице, но те данные, которые не должны быть изменены клиентом, должны содержать дополнительную защиту. Например, второе скрытое поле с подписью, вычисленной на сервере, или хэшем соленого значения, вычисленным на сервере. Когда данные возвращаются в следующем запросе к серверу, он должен пересчитать и сравнить сигнатуру / хэш с той же солью и проверить, что переданное значение и вычисленное значение совпадают. Конечно, клиент не должен знать секрет, который вы используете для вычисления подписи или соли, используемой в хэше.

Я прочитал, что мне просто нужно иметь репозиторий Document в качестве совокупности и потерять репозиторий Note, но я не уверен, поможет ли это / как это.

Это более чистый способ использования репозиториев, но он не поможет вам с вашей конкретной ошибкой, потому что вам все еще понадобятся Note и DocumentId.

...