LINQ에서 전체 텍스트 검색 (FTS)을 사용할 수 있습니까?
.NET Framework 3.5를 사용하여 LINQ에서 FTS를 사용할 수 있는지 궁금합니다. 아직 유용하지 않은 문서를 검색하고 있습니다.
누구든지 이것에 대한 경험이 있습니까?
예. 그러나 먼저 SQL 서버 함수를 만들고 기본적으로 LINQ가 like를 사용하므로 호출해야합니다.
자세한 내용을 설명하는 이 블로그 게시물 은 발췌 내용입니다.
작동하게하려면 전달한 키워드를 기반으로 CONTAINSTABLE 쿼리 만 수행하는 테이블 값 함수를 만들어야합니다.
create function udf_sessionSearch (@keywords nvarchar(4000)) returns table as return (select [SessionId],[rank] from containstable(Session,(description,title),@keywords))
그런 다음이 함수를 LINQ 2 SQL 모델에 추가하면 다음과 같은 쿼리를 작성할 수 있습니다.
var sessList = from s in DB.Sessions join fts in DB.udf_sessionSearch(SearchText) on s.sessionId equals fts.SessionId select s;
아니요. LINQ To SQL에서는 전체 텍스트 검색이 지원되지 않습니다.
그것은 당신이 말했다 수 FTS를 이용하여 저장 프로 시저를 사용하고 그에서 LINQ SQL 쿼리 풀 데이터가 있습니다.
나는 그렇게 믿지 않는다. 필드에 'contains'를 사용할 수 있지만 LIKE
쿼리 만 생성 합니다. 전체 텍스트를 사용하려면 저장된 proc을 사용하여 쿼리를 수행 한 다음 LINQ로 다시 전달하는 것이 좋습니다.
조인을 만들고 싶지 않고 C # 코드를 단순화하려는 경우 SQL 함수를 만들어 "from"절에서 사용할 수 있습니다.
CREATE FUNCTION ad_Search
(
@keyword nvarchar(4000)
)
RETURNS TABLE
AS
RETURN
(
select * from Ad where
(CONTAINS(Description, @keyword) OR CONTAINS(Title, @keyword))
)
DBML을 업데이트 한 후 linq에서 사용하십시오.
string searchKeyword = "word and subword";
var result = from ad in context.ad_Search(searchKeyword)
select ad;
이렇게하면 다음과 같은 간단한 SQL이 생성됩니다.
SELECT [t0].ID, [t0].Title, [t0].Description
FROM [dbo].[ad_Search](@p0) AS [t0]
이것은 ad_Search 함수 구현에서 볼 수 있듯이 여러 열에 의한 검색에서 작동합니다.
아니요, 전체 텍스트 검색은 SQL Server에만 해당됩니다 (텍스트가 단어로 인덱싱되고 쿼리가이 인덱스를 적중하는 것과 문자 배열을 순회하는 것). Linq는이를 지원하지 않습니다. 모든 .Contains () 호출은 관리되지 않는 문자열 함수에 도달하지만 인덱싱의 이점은 없습니다.
SQL Server의 CONTAINS 전용이고 와일드 카드 열은없는 작업 프로토 타입을 만들었습니다 . 이것이 달성하는 것은 일반 LINQ 함수처럼 CONTAINS 를 사용하는 것입니다.
var query = context.CreateObjectSet<MyFile>()
.Where(file => file.FileName.Contains("pdf")
&& FullTextFunctions.ContainsBinary(file.FileTable_Ref.file_stream, "Hello"));
필요할 것이예요:
1. CONTAINS 키워드 를 지원하기위한 코드 및 EDMX의 함수 정의 .
2. EFProviderWrapperToolkit / EFTracingProvider로 EF SQL을 다시 작성합니다. CONTAINS는 함수가 아니고 기본적으로 생성 된 SQL이 결과를 bit 로 처리하기 때문 입니다.
그러나:
1. 포함은 실제로 함수가 아니며 부울 결과를 선택할 수 없습니다. 조건에서만 사용할 수 있습니다.
2. 쿼리에 특수 문자가있는 매개 변수화되지 않은 문자열이 포함 된 경우 아래의 SQL 재 작성 코드가 손상 될 수 있습니다.
내 프로토 타입의 출처
기능 정의 : (EDMX)
edmx : StorageModels / Schema에서
<Function Name="conTAINs" BuiltIn="true" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" ReturnType="bit" Schema="dbo">
<Parameter Name="dataColumn" Type="varbinary" Mode="In" />
<Parameter Name="keywords" Type="nvarchar" Mode="In" />
</Function>
<Function Name="conTAInS" BuiltIn="true" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" ReturnType="bit" Schema="dbo">
<Parameter Name="textColumn" Type="nvarchar" Mode="In" />
<Parameter Name="keywords" Type="nvarchar" Mode="In" />
</Function>
추신 : 문자의 이상한 경우는 다른 매개 변수 유형 (varbinary 및 nvarchar)으로 동일한 기능을 활성화하는 데 사용됩니다.
기능 정의 : (코드)
using System.Data.Objects.DataClasses;
public static class FullTextFunctions
{
[EdmFunction("MyModel.Store", "conTAINs")]
public static bool ContainsBinary(byte[] dataColumn, string keywords)
{
throw new System.NotSupportedException("Direct calls are not supported.");
}
[EdmFunction("MyModel.Store", "conTAInS")]
public static bool ContainsString(string textColumn, string keywords)
{
throw new System.NotSupportedException("Direct calls are not supported.");
}
}
추신 : "MyModel.Store" 는 edmx : StorageModels / Schema / @ Namespace의 값과 동일합니다.
EF SQL 다시 작성 : (EFProviderWrapperToolkit에 의해)
using EFProviderWrapperToolkit;
using EFTracingProvider;
public class TracedMyDataContext : MyDataContext
{
public TracedMyDataContext()
: base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
"name=MyDataContext", "EFTracingProvider"))
{
var tracingConnection = (EFTracingConnection) ((EntityConnection) Connection).StoreConnection;
tracingConnection.CommandExecuting += TracedMyDataContext_CommandExecuting;
}
protected static void TracedMyDataContext_CommandExecuting(object sender, CommandExecutionEventArgs e)
{
e.Command.CommandText = FixFullTextContainsBinary(e.Command.CommandText);
e.Command.CommandText = FixFullTextContainsString(e.Command.CommandText);
}
private static string FixFullTextContainsBinary(string commandText, int startIndex = 0)
{
var patternBeg = "(conTAINs(";
var patternEnd = ")) = 1";
var exprBeg = commandText.IndexOf(patternBeg, startIndex, StringComparison.Ordinal);
if (exprBeg == -1)
return commandText;
var exprEnd = FindEnd(commandText, exprBeg + patternBeg.Length, ')');
if (commandText.Substring(exprEnd).StartsWith(patternEnd))
{
var newCommandText = commandText.Substring(0, exprEnd + 2) + commandText.Substring(exprEnd + patternEnd.Length);
return FixFullTextContainsBinary(newCommandText, exprEnd + 2);
}
return commandText;
}
private static string FixFullTextContainsString(string commandText, int startIndex = 0)
{
var patternBeg = "(conTAInS(";
var patternEnd = ")) = 1";
var exprBeg = commandText.IndexOf(patternBeg, startIndex, StringComparison.Ordinal);
if (exprBeg == -1)
return commandText;
var exprEnd = FindEnd(commandText, exprBeg + patternBeg.Length, ')');
if (exprEnd != -1 && commandText.Substring(exprEnd).StartsWith(patternEnd))
{
var newCommandText = commandText.Substring(0, exprEnd + 2) + commandText.Substring(exprEnd + patternEnd.Length);
return FixFullTextContainsString(newCommandText, exprEnd + 2);
}
return commandText;
}
private static int FindEnd(string commandText, int startIndex, char endChar)
{
// TODO: handle escape chars between parens/squares/quotes
var lvlParan = 0;
var lvlSquare = 0;
var lvlQuoteS = 0;
var lvlQuoteD = 0;
for (var i = startIndex; i < commandText.Length; i++)
{
var c = commandText[i];
if (c == endChar && lvlParan == 0 && lvlSquare == 0
&& (lvlQuoteS % 2) == 0 && (lvlQuoteD % 2) == 0)
return i;
switch (c)
{
case '(':
++lvlParan;
break;
case ')':
--lvlParan;
break;
case '[':
++lvlSquare;
break;
case ']':
--lvlSquare;
break;
case '\'':
++lvlQuoteS;
break;
case '"':
++lvlQuoteD;
break;
}
}
return -1;
}
}
EFProviderWrapperToolkit 활성화 :
nuget으로 가져 오면 app.config 또는 web.config에 다음 줄을 추가해야합니다.
<system.data>
<DbProviderFactories>
<add name="EFTracingProvider" invariant="EFTracingProvider" description="Tracing Provider Wrapper" type="EFTracingProvider.EFTracingProviderFactory, EFTracingProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
<add name="EFProviderWrapper" invariant="EFProviderWrapper" description="Generic Provider Wrapper" type="EFProviderWrapperToolkit.EFProviderWrapperFactory, EFProviderWrapperToolkit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
</DbProviderFactories>
</system.data>
참고URL : https://stackoverflow.com/questions/224475/is-it-possible-to-use-full-text-search-fts-with-linq
'Nice programing' 카테고리의 다른 글
OnClickListener-x, y 이벤트 위치? (0) | 2020.10.19 |
---|---|
MongoDB-페이징 (0) | 2020.10.19 |
C 함수 구문, 매개 변수 목록 뒤에 선언 된 매개 변수 유형 (0) | 2020.10.19 |
각 루프에 대한 C #은 어떤 순서로 목록을 반복합니까? (0) | 2020.10.19 |
Makefile에서 : =와 =의 차이점은 무엇입니까? (0) | 2020.10.19 |