SQL Server 2008 전체 텍스트 인덱스 '포함'키워드 용 NHibernate LinqToHqlGenerator

데이비드 몽고메리

LinqToHql 생성기 클래스를 구현할 때 근본적인 것을 놓치고 있다고 생각합니다.

contains이 등록과 함께 사용자 지정 언어를 사용하여 SQL Server 2008 쿼리를 성공적으로 등록했습니다 .

RegisterFunction("contains", new StandardSQLFunction("contains", null));

쿼리 할 전체 텍스트 인덱스가있는 클래스가 하나만 있습니다.

public class SearchName
{
  public virtual Guid Id {get; set;}
  public virtual string Name {get; set;} // this is the search field
}

contains 함수는 HQL에서 제대로 작동합니다.

var names = Session.CreateQuery("from SearchName where contains(Name,:keywords)")
                    .SetString("keywords", "john")
                    .List();

생성 된 SQL은 완벽합니다.

select searchname0_.Id   as Id4_,
       searchname0_.Name as Name4_
from   Search_Name searchname0_
where  contains(searchname0_.Name, 'john' /* @p0 */)

다음 과제는 Linq to HQL 생성기를 구현하는 것이 었습니다.

 public class MyLinqtoHqlGeneratorsRegistry :
    DefaultLinqToHqlGeneratorsRegistry
    {
        public MyLinqtoHqlGeneratorsRegistry()
        {
            this.Merge(new ContainsGenerator());
        }
    }

    public class ContainsGenerator : BaseHqlGeneratorForMethod
    {
        public ContainsGenerator()
        {
            SupportedMethods = new[] {
                ReflectionHelper.GetMethodDefinition<SearchName>(d => d.Name.Contains(String.Empty))
          };
        }

        public override HqlTreeNode BuildHql(MethodInfo method,
          System.Linq.Expressions.Expression targetObject,
          ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
          HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            return treeBuilder.MethodCall("contains",
                    visitor.Visit(targetObject).AsExpression(),
                    visitor.Visit(arguments[0]).AsExpression()
                );
        }
    }
}

다음과 같이 메서드를 호출합니다.

var namesLinq = Session.Query<SearchName>().Where(x=> x.Name.Contains("john")).ToList();

불행히도 이것은 내장 Contains메서드 를 재정의하지 않는 것 같 으며 생성 된 SQL이 잘못되었습니다.

select searchname0_.Id   as Id4_,
       searchname0_.Name as Name4_
from   Search_Name searchname0_
where  searchname0_.Name like ('%' + 'john' /* @p0 */ + '%')

기본 Contains방법 을 재정의 할 수 없거나 어리석은 실수를 한 적이 있습니까?

추신-저는 NHibernate 3.3.1.4000을 사용하고 있습니다.

데이비드 몽고메리

좋아, 마침내 알아 냈어!

먼저 내 구성에서 등록 코드를 삭제했습니다.

...
.ExposeConfiguration(cfg =>
     {
        cfg.LinqToHqlGeneratorsRegistry<MyLinqtoHqlGeneratorsRegistry>();
        ...
     }

둘째, 기존 Linq 동작을 재정의하지 마십시오. 내 Contains 확장 메서드를 전체 텍스트 클래스로 옮겼습니다.

셋째, Hql 트리를 올바르게 구축하십시오.

SQL 2008 자유 텍스트 포함 검색을 구현하려는 다른 사용자를 위해 다음은 전체 구현입니다.

public static class DialectExtensions
    {
        public static bool Contains(this SearchName sn, string searchString)
        {
            // this is just a placeholder for the method info.  
            // It does not otherwise matter.
            return false;
        }
    }

    public class MyLinqtoHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
    {
        public MyLinqtoHqlGeneratorsRegistry()
            : base()
        {
            RegisterGenerator(ReflectionHelper.GetMethod(() =>
                 DialectExtensions.Contains(null, null)),
                 new ContainsGenerator());
        }
    }

    public class ContainsGenerator : BaseHqlGeneratorForMethod
    {
        string fullTextFieldName = "Name";

        public ContainsGenerator()
            : base()
        {
            SupportedMethods = new[] {
                ReflectionHelper.GetMethodDefinition(() =>
                DialectExtensions.Contains(null, null))
          };
        }

        public override HqlTreeNode BuildHql(MethodInfo method,
          System.Linq.Expressions.Expression targetObject,
          ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
          HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            // cannot figure out how to interrogate the model class to get an 
            // arbitrary field name...
            // perhaps the RegisterGenerator() call above could be used to pass a
            // property name to the ContainsGenerator constructor?
            // in our case, we only have one full text searchable class, and its
            // full-text searchable field is "Name"
            HqlExpression[] args = new HqlExpression[2] {
                 treeBuilder.Ident(fullTextFieldName).AsExpression(),
                 visitor.Visit(arguments[1]).AsExpression() 
                 };
            return treeBuilder.BooleanMethodCall("contains", args);
        }
    }

위의 기능이 작동하려면 사용자 지정 방언을 선언하고 사용해야합니다.

public class CustomMsSql2008Dialect : NHibernate.Dialect.MsSql2008Dialect
{
    public CustomMsSql2008Dialect()
    {
        RegisterFunction(
            "contains",
            new StandardSQLFunction("contains", null)
            );
    }
}

그런 다음 다음과 같은 방법으로 새 ​​포함 검색을 사용할 수 있습니다.

var namesLinq = Session.Query<SearchName>().Where(x => x.Contains("john")).ToList();

... 그리고 결과 SQL은 완벽합니다! (적어도 전체 텍스트 검색을 수행하는 테이블이 하나만있는 경우)

수정 : 쿼리 당 하나 이상의 전체 텍스트 '포함'검색을 지원하도록 구현이 업데이트되었습니다.

수정 된 버전은 다음과 같습니다.

public static class DialectExtensions
    {
        public static bool FullTextContains(this string source, string pattern)
        {
            return false;
        }
    }

    public class MyLinqtoHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
    {
        public MyLinqtoHqlGeneratorsRegistry()
            : base()
        {
            RegisterGenerator(ReflectionHelper.GetMethod(() => DialectExtensions.FullTextContains(null, null)),
                          new FullTextContainsGenerator());
        }
    }

    public class FullTextContainsGenerator : BaseHqlGeneratorForMethod
    {
        public FullTextContainsGenerator()
        {
            SupportedMethods = new[] { ReflectionHelper.GetMethod(() => DialectExtensions.FullTextContains(null, null)) };
        }

        public override HqlTreeNode BuildHql(MethodInfo method,
          System.Linq.Expressions.Expression targetObject,
          ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
          HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            HqlExpression[] args = new HqlExpression[2] { 
                visitor.Visit(arguments[0]).AsExpression(),
                visitor.Visit(arguments[1]).AsExpression() 
            };
            return treeBuilder.BooleanMethodCall("contains", args);
        }
    }

수정 된 버전을 사용하려면 구문이 약간 다릅니다.

var namesLinq = Session.Query<SearchName>().Where(x => x.Name.FullTextContains("john")).ToList();

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

SQL Server 전체 텍스트 인덱스 쿼리

분류에서Dev

SQL Server 2012의 수동 전체 텍스트 인덱스 채우기 시간

분류에서Dev

SQL Server 전체 텍스트 검색에 일치하는 전체 단어 만 포함됨

분류에서Dev

SQL Server 2008 T-SQL : 증가하는 숫자 공간 PER 외래 키 값을 구현하는 방법 (스레드 안전성 포함)

분류에서Dev

SQL Server 비 클러스터형 인덱스-값 포함

분류에서Dev

SQL 주입을 사용한 전체 텍스트 검색이 포함 된 ADO select 문

분류에서Dev

북유럽 문자를 사용한 SQL Server 전체 텍스트 검색

분류에서Dev

다른 인덱스에 열을 포함하여 SQL Server에서 클러스터되지 않은 인덱스를 '체인'할 수 있습니까?

분류에서Dev

자동 증분 인덱스 SQL Server, Oracle DB 및 MySQL (InnoDB 포함)

분류에서Dev

전체 텍스트 인덱스 검색의 여러 단어-SQL

분류에서Dev

SQL Server 2008 R2 복제를 위해 스키마에 기본값 설정을 포함하는 방법

분류에서Dev

SQL Server 인덱스 사용 재설정

분류에서Dev

SQL Server 전체 텍스트 검색-총 필드 값 가져 오기

분류에서Dev

iFTS 자유 텍스트 SQL Server 2014 다중 열 배수 키워드

분류에서Dev

JSON-LD의 최상위 인덱스 전용 키에 대한 컨텍스트

분류에서Dev

bash는 키워드를 포함하는 마커로 구분 된 텍스트의 일부를 대체합니다.

분류에서Dev

이전 한 열의 가중치 열을 사용한 SQL Server 전체 텍스트 검색

분류에서Dev

SQL Server-nvarchar 필드의 인덱스

분류에서Dev

최신 SQL Server Reporting Services의 전체 텍스트 근거

분류에서Dev

SQL Server 2005에서 SQL Server 2008로 마이그레이션 : 테이블 이름 앞에 스키마 이름을 사용해야 함

분류에서Dev

SQL 쿼리를 사용하여 테이블의 클러스터형 인덱스를 참조하는 SQL Server 2008 R2

분류에서Dev

Windows 7 / Windows Server 2008 용 대체 콘솔 호스트

분류에서Dev

텍스트 파일에서 키워드 검색 및 전체 행 인쇄

분류에서Dev

SQL Server 2008 : 동의어에 대한 모든 인덱스 비활성화

분류에서Dev

SQL Server의 모든 인덱스 열 (필터링 된 열 포함) 나열

분류에서Dev

Azure SQL 전체 텍스트 인덱스 초기 채우기 속도가 느림

분류에서Dev

CakePHP3 전체 텍스트 인덱스 일치에서 SQL 삽입 방지

분류에서Dev

"삽입 전용"스키마에 대한 적절한 SQL 서버 인덱스

분류에서Dev

해시 태그에 대한 MySQL 전체 텍스트 검색 (인덱스의 # 기호 포함)

Related 관련 기사

  1. 1

    SQL Server 전체 텍스트 인덱스 쿼리

  2. 2

    SQL Server 2012의 수동 전체 텍스트 인덱스 채우기 시간

  3. 3

    SQL Server 전체 텍스트 검색에 일치하는 전체 단어 만 포함됨

  4. 4

    SQL Server 2008 T-SQL : 증가하는 숫자 공간 PER 외래 키 값을 구현하는 방법 (스레드 안전성 포함)

  5. 5

    SQL Server 비 클러스터형 인덱스-값 포함

  6. 6

    SQL 주입을 사용한 전체 텍스트 검색이 포함 된 ADO select 문

  7. 7

    북유럽 문자를 사용한 SQL Server 전체 텍스트 검색

  8. 8

    다른 인덱스에 열을 포함하여 SQL Server에서 클러스터되지 않은 인덱스를 '체인'할 수 있습니까?

  9. 9

    자동 증분 인덱스 SQL Server, Oracle DB 및 MySQL (InnoDB 포함)

  10. 10

    전체 텍스트 인덱스 검색의 여러 단어-SQL

  11. 11

    SQL Server 2008 R2 복제를 위해 스키마에 기본값 설정을 포함하는 방법

  12. 12

    SQL Server 인덱스 사용 재설정

  13. 13

    SQL Server 전체 텍스트 검색-총 필드 값 가져 오기

  14. 14

    iFTS 자유 텍스트 SQL Server 2014 다중 열 배수 키워드

  15. 15

    JSON-LD의 최상위 인덱스 전용 키에 대한 컨텍스트

  16. 16

    bash는 키워드를 포함하는 마커로 구분 된 텍스트의 일부를 대체합니다.

  17. 17

    이전 한 열의 가중치 열을 사용한 SQL Server 전체 텍스트 검색

  18. 18

    SQL Server-nvarchar 필드의 인덱스

  19. 19

    최신 SQL Server Reporting Services의 전체 텍스트 근거

  20. 20

    SQL Server 2005에서 SQL Server 2008로 마이그레이션 : 테이블 이름 앞에 스키마 이름을 사용해야 함

  21. 21

    SQL 쿼리를 사용하여 테이블의 클러스터형 인덱스를 참조하는 SQL Server 2008 R2

  22. 22

    Windows 7 / Windows Server 2008 용 대체 콘솔 호스트

  23. 23

    텍스트 파일에서 키워드 검색 및 전체 행 인쇄

  24. 24

    SQL Server 2008 : 동의어에 대한 모든 인덱스 비활성화

  25. 25

    SQL Server의 모든 인덱스 열 (필터링 된 열 포함) 나열

  26. 26

    Azure SQL 전체 텍스트 인덱스 초기 채우기 속도가 느림

  27. 27

    CakePHP3 전체 텍스트 인덱스 일치에서 SQL 삽입 방지

  28. 28

    "삽입 전용"스키마에 대한 적절한 SQL 서버 인덱스

  29. 29

    해시 태그에 대한 MySQL 전체 텍스트 검색 (인덱스의 # 기호 포함)

뜨겁다태그

보관