我可以使用映射到单个列的多个属性查询UserType吗?

时间:2011-05-01 01:13:31

标签: c# nhibernate usertype

我有以下域名模型:

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 个答案:

答案 0 :(得分:5)

我不是一个nhibernate用户,但是分析我们在这里有关该场景的所有信息,我有一种强烈的感觉,答案是你不能。

您正在将该类中包含的值映射到db中的单个值。

为了允许查询它的部分,它必须理解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();

并非在所有情况下,您都在从连接数据转换为解析数据。你是唯一一个知道这是否真的为你买东西的人,而不是单独保留属性。

答案 1 :(得分:3)

我相信这是可能的,但需要在SQL方面做一些工作。我可能会尝试的第一件事是创建一种类型的UDF,它将为您分割名称并进行必要的比较。然后,您可以扩展NHibernate以映射到此UDF,并且您能够从查询中调用此函数,无论是基于SQL,HQL还是基于ICriteria。

答案 2 :(得分:0)

您只能查询全名,因为它只是一个数据库字段。

如果您以不同的方式映射,以便FirstName和Lastname是单独的列,您应该能够查询每个列,但您可能难以查询名为FullName的属性。

答案 3 :(得分:0)

您可以做的是为这些对象实现自己的存储库包装器,并实现GetUsersByLastName()等可以使用HQL执行这些类型的“按部分值搜索”查询的方法。

如果您传递了正确的搜索字符串,则以下内容应允许您按任何部分值进行搜索:

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

编辑:

从查询中删除LastName。这将起作用的方式是您将锚定的搜索文本用于BirthName字段的开头或结尾。例如,如果您想搜索姓氏为Smith的所有人,您可以这样做:

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 %'";

答案 4 :(得分:0)

您需要创建计算列。它们是只读的,但您可以查询它们。请参阅here