Получение объекта из хранилища по пользовательской строке - PullRequest
0 голосов
/ 30 апреля 2010

Что считается хорошей практикой для запроса объектов из базы данных с использованием простой строки в качестве параметров запроса. Кто должен реализовать метод, который «преобразует» строку в сущность, и кто должен вызывать этот метод? Хранилище, сущность или какой-либо другой объект, например контроллер в приложении MVC?

Для более конкретного примера у меня есть приложение ASP.NET MVC 2, использующее IRepository и SharpModelBinder Sharp Architecture. Последний настроен так, что если пользователь отправляет форму с идентификатором вместо объекта, он запрашивает соответствующий репозиторий для объекта с таким же идентификатором. Я хотел бы добавить к этому примеру, чтобы иметь возможность использовать не только идентификатор, но и пользовательскую строку. Конечно, метод, который получает конкретный идентификатор из общей строки запроса, отличается для каждого репозитория / сущности. Как мне это сделать?

Чтобы быть еще более конкретным. Предположим, у меня есть две сущности:

class Doctor : Entity {
    public virtual Patient ActualPatient { get; set; };
    // some other properties, constructor, etc.
}

class Patient : Entity {
    // some properties, constructor, etc.
}

Теперь, если у меня есть редактор для сущности Доктор (например, форма), я мог бы ввести идентификатор вместо Doctor.ActualPatient, и механизм связывания модели позаботится о назначении соответствующего объекта. Но что, если пользователь вводит пользовательскую строку (например, имя Patient)?

Вот мои текущие параметры:

  1. Контроллер должен позаботиться об этой пользовательской строке. Таким образом, после того, как ModelBinder не может связать Patient с Doctor (= возвращает null для Patient), контроллер берет строку и, используя некоторый алгоритм, пытается получить Patient, который представлен этой строкой (или тоже не получается)
  2. Контроллер заботится об этом, но вызывает метод, который определен где-то еще, но не в классе Controller (см. Следующий вопрос)
  3. ModelBinder должен быть настроен для использования этого внешнего метода
  4. Вы никогда не должны делать что-то подобное, это всегда считается плохой практикой
  5. Что-то еще (предложения приветствуются)

И вот мои предложения о том, где этот метод должен быть реализован:

  1. В репозитории должен быть метод GetEntityFromAString(string), и подклассы для этого репозитория должны переопределить этот метод.
  2. У сущности должен быть Атрибут, который, если он присутствует, заботится об этом преобразовании, и контроллер / связующий элемент модели / etc проверяет этот атрибут и вызывает метод, подобный GetEntityFromAStringUsingThisRepository(string,repository)
  3. Я уже говорил, что это плохая практика
  4. Что-то еще

Хотя конкретный пример для Sharp Architecture / ASP.NET MVC2 / NHibernate, не стесняйтесь отвечать на него в целом.

Спасибо за ответы.

1 Ответ

1 голос
/ 01 мая 2010

Я бы управлял этим явно с контроллера.

Если вы связываетесь по ID, вы можете гарантировать, что получите либо экземпляр, либо ноль, если он не найден. Но связывание с произвольным свойством не так просто: что, если есть несколько совпадений? Должен ли переплетчик создавать исключение? Должен ли он вернуть только первый результат? Как видите, неожиданные результаты легко получить, нарушая принцип наименьшего удивления .

Если вы действительно знаете, что делаете, и вам это нужно, я бы создал пользовательский связыватель со связанным атрибутом, который будет иметь имя свойства, которое будет использоваться для поиска сущности например,

class Patient {
  int Id {get;set;}
  string PatientName {get;set;}
}
...
ActionResult SomeAction([MyCustomBinder("PatientName")] Patient patient) {...}
...