C# 在 Linq 查询中调用方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9970100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling a method inside a Linq query
提问by user990635
I want to insert into my table a column named 'S' that will get some string value based on a value it gets from a table column.
我想在我的表中插入一个名为“S”的列,该列将根据从表列中获取的值获取一些字符串值。
For example: for each ID (a.z)I want to gets it's string value stored in another table. The string value is returned from another method that gets it through a Linq query.
例如:for each ID (a.z)我想获取存储在另一个表中的字符串值。字符串值是从另一个通过 Linq 查询获取它的方法返回的。
- Is it possible to call a method from Linq?
- Should I do everything in the same query?
- 是否可以从 Linq 调用方法?
- 我应该在同一个查询中做所有事情吗?
This is the structure of the information I need to get:
这是我需要获取的信息的结构:
a.z is the ID in the first square in table #1, from this ID I get another id in table #2, and from that I can get my string value that I need to display under column 'S'.
az 是表 #1 中第一个方块中的 ID,从这个 ID 中我得到表 #2 中的另一个 id,从中我可以获得我需要在列“S”下显示的字符串值。
var q = (from a in v.A join b in v.B
on a.i equals b.j
where a.k == "aaa" && a.h == 0
select new {T = a.i, S = someMethod(a.z).ToString()})
return q;
The line S = someMethod(a.z).ToString()causing the following error:
S = someMethod(a.z).ToString()导致以下错误的行:
Unable to cast object of type 'System.Data.Linq.SqlClient.SqlColumn' to type 'System.Data.Linq.SqlClient.SqlMethodCall'.
无法将“System.Data.Linq.SqlClient.SqlColumn”类型的对象转换为“System.Data.Linq.SqlClient.SqlMethodCall”类型。
采纳答案by BrokenGlass
You have to execute your method call in Linq-to-Objectscontext, because on the database side that method call will not make sense - you can do this using AsEnumerable()- basically the rest of the query will then be evaluated as an in memory collection using Linq-to-Objectsand you can use method calls as expected:
您必须在Linq-to-Objects上下文中执行您的方法调用,因为在数据库端,该方法调用没有意义 - 您可以使用AsEnumerable()- 基本上查询的其余部分将被评估为内存中的集合Linq-to-Objects,您可以使用方法按预期调用:
var q = (from a in v.A join b in v.B
on a.i equals b.j
where a.k == "aaa" && a.h == 0
select new {T = a.i, Z = a.z })
.AsEnumerable()
.Select(x => new { T = x.T, S = someMethod(x.Z).ToString() })
回答by Ken Smith
You'll want to split it up into two statements. Return the results from the query (which is what will hit the database), and then enumerate the results a second time in a separate step to transform the translation into the new object list. This second "query" won't hit the database, so you'll be able to use the someMethod()inside it.
您需要将其拆分为两个语句。从查询中返回结果(这将命中数据库),然后在单独的步骤中再次枚举结果以将翻译转换为新的对象列表。第二个“查询”不会访问数据库,因此您将能够使用其中的someMethod()内容。
Linq-to-Entities is a bit of a strange thing, because it makes the transition to querying the database from C# extremely seamless: but you always have to remind yourself, "This C# is going to get translated into some SQL." And as a result, you have to ask yourself, "Can all this C# actually get executed as SQL?" If it can't - if you're calling someMethod()inside it - your query is going to have problems. And the usual solution is to split it up.
Linq-to-Entities 有点奇怪,因为它使从 C# 查询数据库的过渡非常无缝:但您必须始终提醒自己,“这个 C# 将被翻译成一些 SQL。” 因此,您必须问自己,“所有这些 C# 真的可以作为 SQL 执行吗?” 如果它不能——如果你在someMethod()里面打电话——你的查询就会有问题。通常的解决方案是将其拆分。
(The other answer from @BrokenGlass, using .AsEnumerable(), is basically another way to do just that.)
(@BrokenGlass 的另一个答案,使用.AsEnumerable(), 基本上是另一种方法。)
回答by Giedrius
That is an old question, but I see nobody mention one "hack", that allows to call methods during select without reiterating. Idea is to use constructor and in constructor you can call whatever you wish (at least it works fine in LINQ with NHibernate, not sure about LINQ2SQL or EF, but I guess it should be the same). Below I have source code for benchmark program, it looks like reiterating approach in my case is about twice slower than constructor approach and I guess there's no wonder - my business logic was minimal, so things like iteration and memory allocation matters.
这是一个老问题,但我看到没有人提到一个“hack”,它允许在 select 期间调用方法而无需重申。想法是使用构造函数,在构造函数中你可以随意调用(至少它在 LINQ 和 NHibernate 中工作正常,不确定 LINQ2SQL 或 EF,但我想它应该是一样的)。下面我有基准程序的源代码,在我的情况下,似乎重复方法比构造函数方法慢两倍,我想这不足为奇 - 我的业务逻辑很小,所以迭代和内存分配之类的事情很重要。
Also I wished there was better way to say, that this or that should not be tried to execute on database,
我也希望有更好的说法,不应该尝试在数据库上执行这个或那个,
// Here are the results of selecting sum of 1 million ints on my machine:
// Name Iterations Percent
// reiterate 294 53.3575317604356%
// constructor 551 100%
public class A
{
public A()
{
}
public A(int b, int c)
{
Result = Sum(b, c);
}
public int Result { get; set; }
public static int Sum(int source1, int source2)
{
return source1 + source2;
}
}
class Program
{
static void Main(string[] args)
{
var range = Enumerable.Range(1, 1000000).ToList();
BenchmarkIt.Benchmark.This("reiterate", () =>
{
var tst = range
.Select(x => new { b = x, c = x })
.AsEnumerable()
.Select(x => new A
{
Result = A.Sum(x.b, x.c)
})
.ToList();
})
.Against.This("constructor", () =>
{
var tst = range
.Select(x => new A(x, x))
.ToList();
})
.For(60)
.Seconds()
.PrintComparison();
Console.ReadKey();
}
}


