将SQL Server的CONTAINS()导入为模型定义的函数

时间:2012-01-26 09:31:56

标签: sql-server entity-framework entity-framework-4.1 full-text-search

我正在尝试在我的Entity Framework模型中导入SQL Server的CONTAINS()函数,以便我可以在LINQ查询中使用它。

我已将此添加到我的EDM中:

<Function Name="FullTextSearch" ReturnType="Edm.Boolean">
    <Parameter Name="Filter" Type="Edm.String" />
    <DefiningExpression>
        CONTAINS(*, Filter)
    </DefiningExpression>
</Function>

添加创建我的方法存根:

[EdmFunction("MyModelNamespace", "FullTextSearch")]
public static bool FullTextSearch(string filter)
{
    throw new NotSupportedException("This function is only for L2E query.");
}

我尝试像这样调用函数:

from product in Products
where MyModel.FullTextSearch("FORMSOF(INFLECTIONAL, robe)")
select product

引发以下异常:

The query syntax is not valid. Near term '*'

我意识到我定义的函数没有直接链接到被查询的实体集,所以这也可能是一个问题。

有什么方法可以解决这个问题吗?

3 个答案:

答案 0 :(得分:3)

您在上面定义的函数使用的是Entity SQL,而不是Transact SQL,因此我认为第一步是确定是否可以在Entity SQL中表达CONTAINS(*,'text')。

实体SQL不支持*运算符,如下所述:http://msdn.microsoft.com/en-us/library/bb738573.aspx如果我尝试

entities.CreateQuery<TABLE_NAME>("select value t from TABLE_NAME as t where CONTAINS(*, 'text')");

我得到了你上面的错误。如果我尝试显式传递它的工作原理:

entities.CreateQuery<TABLE_NAME>("select value t from TABLE_NAME as t where CONTAINS(t.COLUMN_NAME, 'text')");

但是当我查看SQL时,它将它转换为LIKE表达式。

ADO.NET:Execute Reader "SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[TABLE_NAME] AS [Extent1]
    WHERE (CASE WHEN ([Extent1].[COLUMN_NAME] LIKE '%text%') THEN cast(1 as bit) WHEN ( NOT ([Extent1].[COLUMN_NAME] LIKE '%text%')) THEN cast(0 as bit) END) = 1
)  AS [GroupBy1]"

如果无法使用Entity SQL表达查询,则必须使用存储过程或其他机制直接使用Transact SQL。

答案 1 :(得分:1)

这超出了我的范围,但你可以试试吗

from product in Products where MyModel.FullTextSearch(product, "FORMSOF(INFLECTIONAL, robe)") select product 

我的理由是在SQL Server中它需要两个参数。

答案 2 :(得分:1)

我在我的代码中插入了一个小函数,在一个继承自Context类的类中,该类指向支持全文搜索的SQL函数,我的解决方案对你的解决方案更加封闭(不允许指定文本搜索的类型),它返回一个IEnumerable,基本上是一个匹配搜索条件的主键列表,如下所示;

public class myContext : DataContext
{

     protected class series_identity
     {
            public int seriesID;

            series_identity() { }
     };

            [Function(Name = "dbo.fnSeriesFreeTextSearchInflectional", IsComposable = true)]
            protected IQueryable<series_identity> SynopsisSearch([Parameter(DbType = "NVarChar")] string value)
            {
                return this.CreateMethodCallQuery<series_identity>(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), value);
            }

            public IEnumerable<int> Search(string value)
            {
                var a = from t1 in SynopsisSearch(value)
                        select t1.seriesID;

                return a;
            }
};

用法就像;

myContext context = new myContext();

IEnumerable<int> series_identities = (from t1 in context.Search("some term")
                                                  select t1).Distinct();