Могу ли я запросить пользовательский тип с несколькими свойствами, нанесенными на один столбец?

StackOverflow https://stackoverflow.com/questions/5845693

  •  27-10-2019
  •  | 
  •  

Вопрос

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

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 работать с этим?

Это было полезно?

Решение

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

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

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

Это означало бы понимание того, что у вас есть код 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();

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

Другие советы

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

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

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

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

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

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

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

Редактировать:

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

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 %'";
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top