我想使用我在查询中创建的方法,因为我需要实现一种特殊类型的过滤器...
return manager.Clients.SelectAll().Where(cli => cli.Name.SatisfyFilter(filter.Name) && cli.LastName.SatisfyFilter(filter.LastName) && cli.MiddleName.SatisfyFilter(filter.MiddleName)).ToList();
但我明白了:
“Method”Boolean SatisfyFilter(System.String,System.String)'没有支持的SQL转换。“
错误
我的方法是:
public static bool SatisfyFilter(this string palavra, string filtro)
与
相同public bool Contains(string value)
在字符串类型中,而Contains工作得很好......
我需要这个方法在IQueryable上运行,因为我的表有2500万个客户......
我在sql profiler上看到包含在sql中转换...
如何实现我的方法将相关的过滤器代码发送到sql? = /
答案 0 :(得分:8)
在SQL服务器上创建一个与C#代码等效的用户函数。说它被称为“dbo.SatsFilter”。
在datacontext覆盖上创建一个方法,如下所示:
public bool SatisfiesFilter(string name, string filter)
{
// some sort of implementation.
}
使用[Function]
和[Parameter]
属性装饰C#方法,使其看起来像:
[Function(Name="dbo.SatsFilter",IsComposable=true)]
public bool SatisfiesFilter([Parameter name="@name",DbType="nvarchar(50)"]string name, [Parameter name="@filter",DbType="nvarchar(50)"]string filter)
IsComposable=true
表示它是一个函数而不是存储过程,因此可以用作更大查询的一部分。
您现在可以使用DataContext的这种方法,并在适当时将其转换为SQL,或者在内存中执行的查询中使用C#。
另请注意,如果您只想一直使用SQL(有时很有用),则可以在C#代码中调用方法时调用SQL:
[Function(Name="dbo.SatsFilter",IsComposable=true)]
public bool SatisfiesFilter([Parameter name="@name",DbType="nvarchar(50)"]string name, [Parameter name="@filter",DbType="nvarchar(50)"]string filter)
{
return (bool)ExecuteMethodCall(this, (MethodInfo)MethodInfo.GetCurrentMethod(), name, filter).ReturnValue;
}
当C#等价物方便时,这不是很有用,因为它意味着对数据库的命中和一些翻译,但是如果用户函数依赖于数据库状态或很难很好地转换为C#
答案 1 :(得分:4)
一个简单的答案是你不能。 LINQ to SQL转换器只识别一些标准的.NET方法,你无法添加其他方法。
如果你需要这样的东西,你需要明确地创建表达式树(用作lambda表达式的主体)。这样做的直接方法是使用Expression
类的方法,但它可以简化很多。
也许最好的选择是使用LINQKit project。它可以调用其他 lambda表达式(不是很方法,但是关闭)。它提供了AsExpandable
扩展方法,允许您编写:
Expression<Func<Purchase, bool>> customFunction = ...
var data = new MyDataContext();
var query =
from c in data.Purchases.AsExpandable()
where customFunction.Compile()(c)
select c.Name;
customFunction
是一个编译为表达式树的lambda函数,您可以在查询中使用它。 AsExpandable
扩展名替换了函数体的用法,因此LINQ to SQL转换器可以处理这个问题。您可以在my blog post中详细了解其工作原理。
其他人讨论的其他替代方案是将功能实现为SQL用户定义的函数。然后,您可以将函数拖动到数据上下文并从查询中调用该函数。翻译人员只需插入对SQL函数的调用。
答案 2 :(得分:1)
如果您可以将其映射到udf,则可以将udf拖到数据上下文中。当通过数据上下文访问时,LINQ-to-SQL可以进行翻译。
如果你只是过滤一个iqueryable,你可以编写一个方法,只使用Where(返回一个新的iqueryable),它可以很好地工作。
如果你需要更多的马克杯,你可能不得不手动弄乱表达树。
答案 3 :(得分:1)
你做了两件事:
答案 4 :(得分:1)
好的解决方案
声明一个类的属性,该类可以转换为远程LINQ执行 与Microsoft.Linq.Translations
答案 5 :(得分:0)
最简单的方法是弄清楚如何将'SatisfyFilter'函数转换为一系列具有可接受翻译的linq命令。我担心没有其他“简单”的方式来使用您的自定义功能,而不会将您的2500万客户端过滤到更具实现性的数字。