【问题标题】:nHibernate method using Criteria for selecting parents for which strings in their child collection contain a certain searchtermnHibernate 方法使用标准来选择其子集合中的字符串包含某个搜索词的父项
【发布时间】:2011-09-01 15:40:16
【问题描述】:

我需要搜索公司地址 - 如果公司在其中一个地址中有特定字符串,它必须出现在搜索结果中(类似于 regex '%string%' )。

公司的 nHibernate 映射文件如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="TaskMappings"
                   namespace="TaskMappings">
    <class name="Company">
        <id name="Id">
            <generator class="sequence">
                <param name="sequence">company_id_seq</param>
            </generator>
        </id>
        <property name="Name" />
        <property name="Fax" />
        <property name="PostalCode" />

        <bag name="Users" cascade="all-delete-orphan" inverse="true">
            <key column="UserCompany" />
            <one-to-many class="User" />
        </bag>

        <bag name="Phone" cascade="all-delete-orphan" lazy="false">
            <key column="PhoneCompany" />
            <element column="Phone" />
        </bag>

        <bag name="Email" cascade="all-delete-orphan" lazy="false">
            <key column="EmailCompany" />
            <element column="Email" />
        </bag>

        <bag name="Addresses" table="address" cascade="all-delete-orphan" lazy="false">
            <key column="AddressCompany" />
            <element column="Address" type="String"/>
        </bag>
    </class>
</hibernate-mapping>

和这样的公司实体类:

public class Company : Entity<int>
{
    public virtual string Name { get; set; }
    public virtual string Fax { get; set; }
    public virtual string PostalCode { get; set; }

    private IList<string> _phone = new List<string>();
    public virtual IList<string> Phone
    {
        get { return _phone; }
        set { _phone = value; }
    }

    private IList<string> _email = new List<string>();
    public virtual IList<string> Email
    {
        get { return _email; }
        set { _email = value; }
    }

    private IList<string> _addresses = new List<string>();
    public virtual IList<string> Addresses
    {
        get { return _addresses; }
        set { _addresses = value; }
    }

    private IList<User> users = new List<User>();
    public virtual IList<User> Users
    {
        get { return users; }
        set { users = value; }
    }
}

我的问题是:我怎样才能更好地使用标准进行搜索?我需要将结果作为 IList。 感谢您的回答! :)

【问题讨论】:

    标签: c# nhibernate criteria


    【解决方案1】:

    你可以试试:

    确保您的地址实体上有一个公司并在其映射中引用它,然后将您的公司实体的地址更改为:

    private IList<Address> _addresses = new List<Address>();
    public virtual IList<Address> Addresses
    {
        get { return _addresses; }
        set { _addresses = value; }
    }
    

    然后试试这个标准:

    var criteria = DetachedCriteria.For<Company>()
       .CreateCriteria("this.Addresses", "a")
       .SetFetchMode("a", FetchMode.Join)
       .Add(Restrictions.InsensitiveLike("a.Address", <string variable>, MatchMode.Anywhere))
       .SetResultTransformer(new DistinctRootEntityTransformer());
    

    然后在您拥有的任何会话中执行该标准。我的问题是,为什么地址映射到公司,而只是一个字符串列表?如果地址是映射到公司的实体,它将为您简化事情。

    【讨论】:

    • 如何使用 DetachedCriteria 来获取 List() 返回?
    • 我想出了如何运行它,但它给出了错误:“集合附近的非法语法:a 描述:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取更多信息有关错误的信息以及它源自代码的位置。异常详细信息:NHibernate.QueryException:集合附近的非法语法:a"
    • 修改了,你可以试试那个。我仍然没有看到像实体一样映射的地址,而只是字符串的集合 - 它是如何在您的数据库中结束的?
    • 在数据库中,地址位于名为 Address 的单独表中,包含 3 个字段:Id、AddressCompany(外键)和 Address(值)。好的。我试试看。
    • 修改了我的答案以包括您提供的有关地址的新详细信息:)
    【解决方案2】:

    看起来这不能使用 Criteria API 完成(尽管我不是 100%)see here for another similar question。但我已经设法使用 HQL 查询使其工作。

    var query = session.CreateQuery("select c from Company c 
    join c.Addresses a where a like '%string%'").List<Company>();
    

    【讨论】:

    • 我收到此错误“错误 1 ​​找不到类型或命名空间名称‘地址’(您是否缺少 using 指令或程序集引用?)”看起来 DetachedCriteria 不起作用带着一个袋子。知道如何让它发挥作用吗?
    • 我的错误我的解决方案不起作用。我会尽快更新我的答案。
    • 感谢您的宝贵时间。我最终不得不选择第四个答案,因为它是使用 Criteria 完成的。
    【解决方案3】:

    类似:

    HibernateDelegate<IList<IAssetLiabilityModel>> del = delegate(ISession session)
        {
            ICriteria criteria = session.CreateCriteria(typeof(ICompany));
            criteria.CreateCriteria("Company.Addresses", "Addresses");
            criteria.Add(Restrictions.Like("Addresses",<your_search_string>)); 
            criteria.SetResultTransformer(CriteriaSpecification.DistinctRootEntity);
            HibernateTemplate.PrepareCriteria(criteria);
            return criteria.List<ICompany>();
        };
        IList<ICompany> companies = HibernateTemplate.Execute(del);
    

    【讨论】:

    • 在什么程序集中我可以找到 HibernateDelegate、HibernateTemplate 等?我是 nHibernate 的初学者,这段代码看起来相当复杂 :)
    • @Freeman,对不起,我目前正在使用 NHibernate,所以我举了一个 NHibernate 的例子,这些东西是 NSpring.Hibernate 的一部分。所以我猜它不适合你。但是你可以删除这些东西。它们仅用于使休眠请求在单独的线程上起作用。虽然您的问题 afaiu 正在创建标准本身
    • @Freeman。哦,今天我瞎了。您正在使用 NHibernate :)。您将在 Spring.Data.NHibernate.Generic 命名空间中找到它。在 Spring.Data.Nhibernate31​​span>
    • @Oleg。我在哪里可以找到 Spring.Data.NHibernate.Generic?我只在引用中添加了 2 个 DLL:NHibernate 和 NHibernate.ByteCode.Castle。
    • @Freeman,如果您不使用 Spring(为什么?恕我直言,它与 NHibernate 结合得很好)。然后省略这些东西(正如我之前所说的)。你已经拥有了你需要的所有 Criteria 代码
    猜你喜欢
    • 2021-07-20
    • 2023-03-09
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    • 2020-05-01
    相关资源
    最近更新 更多