Могу ли я запросить UserType с несколькими свойствами, сопоставленными с одним столбцом? - PullRequest
6 голосов
/ 01 мая 2011

У меня есть следующая модель домена:

public class Name
{
    private readonly string fullName;
    public Name(string fullName) { this.fullName = fullName }
    public string FullName { get { return fullName; } }
    public string FirstName { get { /* ... */ } }
    public string MiddleNames { get { /* ... */ } }
    public string LastName { get { /* ... */ } }
    public static implicit operator Name(string name) { /* ... */ }
}

public class Person
{
    public Name BirthName { get; set; }
    public Name Pseudonym { get; set; }
}

Я реализовал IUserType, поэтому я могу сопоставить каждое имя одному столбцу базы данных с полным именем.

Запросы, подобные этой работе:

var people = session.QueryOver<Person>()
                    .Where(p => p.Name == "John Doe")
                    .List();

Но я не могу сделать такой запрос:

var people = session.QueryOver<Person>()
                    .Where(p => p.Name.LastName == "Doe")
                    .List();

Могу ли я заставить NHibernate работать с этим?

Ответы [ 5 ]

5 голосов
/ 12 мая 2011

Я не большой пользователь nhibernate, но, анализируя всю имеющуюся у нас информацию о сценарии, я чувствую, что ответ на этот вопрос не получится.

Вы отображаете значение, содержащееся в этом классе, в одно значение в БД.

Чтобы разрешить запросы к своим частям, ему нужно понять, как все эти вспомогательные элементы информации в классе Name связаны с полной величиной.

Это означало бы понимание того, что делает ваш собственный код на C #.


обновление 1:

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

Вы можете определенно обойти проблему, как предложено @cs. То есть, определяя пользовательскую функцию, которая делает то, что вы хотите, и отображая это в nHibernate.

По крайней мере, это позволит вам сделать что-то вроде:

session.QueryOver<Person>()
        .Where(p => session.PersonLastName(p) == "Doe")
        .List();

Другим способом было бы определить метод расширения, который переводится в то, что вы хотите, реализуя его, как в этой статье: http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html

Использование тогда будет таким:

 session.QueryOver<Person>()
     .Where(p=> p.Name.LastNameExt() == "Doe")// Ext just to avoid name collision
     .List();

Наконец, я не уверен, возможно ли сопоставить под-свойства с определенными пользователем функциями для каждого, так что ваш запрос может остаться неизменным, например:

 session.QueryOver<Person>()
                .Where(p => p.Name.LastName == "Doe")
                .List();

Не во всех случаях вы переходите от объединения данных к анализу данных. Вы единственный, кто знает, действительно ли это что-то покупает, вместо того, чтобы хранить имущество отдельно.

3 голосов
/ 12 мая 2011

Я считаю, что это возможно, но потребует некоторой работы со стороны SQL. Первое, что я, вероятно, попробую, это создать какой-то UDF, который разделит имя для вас и проведет необходимое сравнение. Затем вы можете расширить NHibernate для отображения на эту UDF, и вы должны иметь возможность вызывать эту функцию из вашего запроса, будь то на основе SQL, HQL или ICriteria.

0 голосов
/ 16 мая 2011

Вам необходимо создать вычисляемые столбцы. Они будут доступны только для чтения, но вы можете запросить их. Смотрите здесь .

0 голосов
/ 16 мая 2011

Что вы можете сделать, это реализовать свою собственную оболочку репозитория для этих объектов и реализовать такие методы, как GetUsersByLastName (), которые могут использовать HQL для выполнения этих типов запросов «поиск по частичным значениям».

Что-то вроде следующего должно позволить вам выполнять поиск по любому частичному значению, если вы передадите правильную строку поиска:

var hql = "select p from People p where lower(p.BirthName) like :searchText";

Edit:

Удалено Фамилия из запроса. Это будет работать так: вы будете использовать привязанный текст поиска к началу или концу поля BirthName. Например, если вы хотите найти всех людей с фамилией Смит, вы можете сделать:

var hql = "select p from People p where lower(p.BirthName) like '% smith'";

А в случае людей с именем Джо:

var hql = "select p from People p where lower(p.BirthName) like 'joe %'";
0 голосов
/ 12 мая 2011

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

Если вы отобразите его по-разному, чтобы FirstName и Lastname были отдельными столбцами, у вас будет возможность запрашивать каждый из них, но тогда у вас могут возникнуть трудности при запросе свойства FullName.

...