LINQ查询中的自定义方法
本文关键字:自定义方法 查询 LINQ | 更新日期: 2023-09-27 18:08:26
我把自己归结为倒霉的人,在LINQ中摸索自定义方法到EF查询。我浏览了网页,试图找出使自定义方法对linq友好的模式,虽然每个来源都说该方法必须是translatable into a T-SQL query
,但应用程序似乎非常多样化。所以,我将把我的代码贴在这里,希望一个慷慨的居民可以告诉我我做错了什么,为什么。
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;
}
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
,它本质上是一个从各种用户文档中挑选出来的单词索引。问题是并不是所有的条目都是单词。数字,甚至下划线行,如___________,
,也会被保存。
我想只保留自定义方法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
条件的记录。
它说它不理解你的IsWord方法在如何将其转换为SQL。
老实说,反正也没什么用,为什么不把它换成
呢?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.
如果返回的不良记录百分比不大,可以考虑先枚举结果集,然后再应用处理/过滤?
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