LINQ查询中的自定义方法

时间:2014-06-13 15:16:28

标签: c# sql linq entity-framework let

我总结自己在LINQ to EF查询中使用自定义方法摸索的不幸事件。我已经浏览了网页,尝试检测一个模式,使自定义方法对LINQ友好,并且虽然每个来源都说该方法必须是translatable into a T-SQL query,但应用程序似乎非常多样化。所以,我会在这里发布我的代码,希望一个慷慨的SO居民可以告诉我我做错了什么以及为什么。

守则

    public IEnumerable<WordIndexModel> GetWordIndex(int transid)
    {
        return (from trindex in context.transIndexes
                let trueWord = IsWord(trindex)
                join trans in context.Transcripts on trindex.transLineUID equals trans.UID
                group new { trindex, trans } by new { TrueWord = trueWord, trindex.transID } into grouped
                orderby grouped.Key.word
                where grouped.Key.transID == transid
                select new WordIndexModel
                {
                    Word = TrueWord,
                    Instances = grouped.Select(test => test.trans).Distinct()
                });

    }

    public string IsWord(transIndex trindex)
    {
        Match m = Regex.Match(trindex.word, @"^[a-z]+(\w*[-]*)*",
                              RegexOptions.IgnoreCase);
        return m.Value;

    }

使用上面的代码,我访问了一个表transIndex,它基本上是从各种用户文档中剔除的单词索引。问题是并非所有条目都是单词。 Nubers,甚至是下划线,例如___________,,也会被保存。

问题

我只想保留我的自定义方法IsWord返回的单词(目前我还没有实际开发过解析机制)。但是,当IsWord函数显示它将返回string

因此,使用let我将自定义方法引入查询并将其用作分组参数,可以选择进入我的对象。在执行时,我得到了全能:

LINQ to Entities does not recognize the method 
'System.String IsWord(transIndex)' method, and this 
method cannot be translated into a store expression."

我还需要确保只返回与IsWord条件匹配的记录。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

据说它在如何将其转换为SQL方面不了解您的IsWord方法。

坦率地说,无论如何都没有做多少,为什么不用

替换它
return (from trindex in context.transIndexes
                let trueWord = trindex.word
                join trans in context.Transcripts on trindex.transLineUID equals trans.UID
                group new { trindex, trans } by new { TrueWord = trueWord, trindex.transID } into grouped
                orderby grouped.Key.word
                where grouped.Key.transID == transid
                select new WordIndexModel
                {
                    Word = TrueWord,
                    Instances = grouped.Select(test => test.trans).Distinct()
                });

EF可以将哪些方法转换为SQL,我无法为您提供列表,但它永远无法翻译您编写的直接方法。但它们是一些内置的,它可以理解,例如MyArray.Contains(x),它可以把它变成类似

的东西
...
WHERE Field IN (ArrItem1,ArrItem2,ArrItem3)

如果你想编写一个linq兼容的方法,那么你需要创建一个EF可以理解并转化为SQL的表达式树。

这就是让我有点兴奋的事情,但这篇文章可能有所帮助http://blogs.msdn.com/b/csharpfaq/archive/2009/09/14/generating-dynamic-methods-with-expression-trees-in-visual-studio-2010.aspx

答案 1 :(得分:1)

如果返回的错误记录百分比不大,您可以考虑首先枚举结果集,然后应用处理/过滤?

var query = (from trindex in context.transIndexes
             ...
             select new WordIndexModel
                {
                    Word,
                    Instances = grouped.Select(test => test.trans).Distinct()
                });
var result = query.ToList().Where(word => IsTrueWord(word));

return result;

如果记录数太高而无法枚举,请考虑在视图或存储过程中进行检查。这将有助于提高速度并保持代码清洁。

但是,当然,使用存储过程具有可重用性和可维护性的缺点(因为没有重构工具)。

另外,请查看另一个与此类似的答案:https://stackoverflow.com/a/10485624/3481183