문제

나는 Ilist에 대한 질문을하려고합니다u003Cstring> nhibernate를 사용하여 내 도메인 클래스 중 하나의 속성. 다음은 간단한 예입니다.

public class Demo
{
    public Demo()
    {
        this.Tags = new List<string>();
    }
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<string> Tags { get; set; }
}

다음과 같이 매핑 :

<class name="Demo">
<id name="Id" />
<property name="Name" />
<bag name="Tags">
  <key column="DemoId"/>
  <element column="Tag" type="String" />
</bag>

그리고 나는 잘 저장하고 검색 할 수 있습니다. 이제 태그 속성에 지정된 값이 포함 된 내 도메인 클래스의 인스턴스에 대해 쿼리하십시오.

var demos = this.session.CreateCriteria<Demo>()
            .CreateAlias("Tags", "t")
            .Add(Restrictions.Eq("t", "a"))
            .List<Demo>();

오류의 결과 : 컬렉션은 연관성이 아니 었습니다 : demo.tags

var demos = (from d in this.session.Linq<Demo>()
                     where d.Tags.Contains("a")
                     select d).ToList();

결과 오류가 발생합니다 : OBJCT 참조는 객체의 인스턴스로 설정되지 않습니다.

var demos = this.session.CreateQuery("from Demo d where :t in elements(d.Tags)")
            .SetParameter("t", "a")
            .List<Demo>();

잘 작동하지만 실제 도메인 클래스에는 많은 속성이 많기 때문에 복잡한 동적 쿼리를 구축하고 있으며 추악한 문자열 조작을 수행하는 것은 나의 첫 번째 선택이 아닙니다. 나는 오히려 icriteria 또는 linq를 사용하고 있습니다. 다양한 가능한 검색 기준을 입력 할 수있는 사용자 인터페이스가 있습니다. 현재 ICRiteria를 구축하는 코드는 수십 줄의 길이입니다. 나는 그것을 HQL 문자열 조작으로 바꾸는 것을 정말로 싫어합니다.

도움이 되었습니까?

해결책

따라서 기준 API의 한계로 인해 도메인 클래스를 구부리기로 결정했습니다.

태그에 대한 엔티티 클래스를 만들었습니다. 나는 그것을 값 객체로 만들 수 없었습니다. 자체 ID가 있어야했습니다.

나는 지금 더럽다. 그러나 문자열 조작에 의지하지 않고 동적 쿼리를 구성 할 수 있다는 것은 도메인에 충실하는 것보다 나에게 더 중요했습니다.

다른 팁

여기에 문서화 된대로 :

17.1.4.1. 별칭 및 속성 참조

우리는 사용할 수 있습니다 :

...
A collection key             {[aliasname].key}      ORGID as {coll.key}
The id of an collection      {[aliasname].id}       EMPID as {coll.id}
The element of an collection {[aliasname].element}  XID as {coll.element}
...

문서에는 작은 버그가 있습니다 ... 대신 ".element" 우리는 사용해야합니다 ".elements"

var demos = this.session.CreateCriteria<Demo>()
        .CreateAlias("Tags", "t")

        // instead of this
        // .Add(Restrictions.Eq("t", "a"))

        // we can use the .elements keyword
        .Add(Restrictions.Eq("t.elements", "a"))

        .List<Demo>();

별명이 아닌 하위 기준을 사용해야합니다. 이것은 작동해야합니다 :

var demos = this.session.CreateCriteria<Demo>()
            .CreateCriteria("Tags")
            .Add(Restrictions.Eq("Tag", "a"))
            .List<Demo>();

HQL :

from Demo d where :val in elements(d.Tags)

문자열 위로 클래스로 전환하는 것은 하나의 타협입니다. ICRiteria 대신 HQL을 사용하는 것이 또 다른 것입니다. 그러나 세 번째 타협은 ... 사용자 정의 SQL을 사용하십시오. 이것을 시도하십시오.

var demos = Session.CreateCriteria<Demo>()
    .Add(Expression.Sql(
        "EXISTS (SELECT 1 FROM [Tags] custom_sql_t WHERE custom_sql_t.[DemoId] = {alias}.[Id] AND custom_sql_t.[Tag] = ?)",
        "a",
        NHibernateUtil.String))
    .List<Demo>();

이로 인해 Follwing SQL이 Nhibernate 2.1.2.4000에 의해 생성됩니다.

exec sp_executesql N'SELECT this_.Id as Id2_0_, this_.Version as Version2_0_, this_.Name as Name2_0_ FROM Demo this_ WHERE EXISTS (SELECT 1 FROM [Tags] custom_sql_t WHERE custom_sql_t.[DemoId] = this_.[Id] AND custom_sql_t.[Tag] = @p0)',N'@p0 nvarchar(1)',@p0=N'a'

다른 예는이 게시물을 참조하십시오 ...

nhibernate- 선택 n+1을 해결하기 위해 값 유형 모음 (비 엔티티)에서 쿼리

이것은 별도의 기준을 만들면 가능합니다.

ICriteria demoCriteria = session.CreateCriteria<Demo>();
...
demoCriteria.Add(Restrictions...);
...
ICriteria tagCriteria = demoCriteria.CreateCriteria("Tags");
tagCriteria.Add(Restrictions.In("elements", new {"Tag1", "Tag2", ...}));

return demoCriteria.List<Demo>();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top