2012-04-02 79 views
24

我想在我的表中插入一個名爲'S'的列,它將根據它從表列獲得的值獲取一些字符串值。調用Linq查詢中的方法

例如:for each ID (a.z)我想獲取它的字符串值存儲在另一個表中。該字符串值是從另一個通過Linq查詢獲取它的方法返回的。

  • 是否可以從Linq調用方法?
  • 我應該在同一個查詢中執行所有操作嗎?

這是信息,我需要得到結構:

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'.
enter image description here

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; 

S = someMethod(a.z).ToString()引起以下錯誤:

Unable to cast object of type 'System.Data.Linq.SqlClient.SqlColumn' to type 'System.Data.Linq.SqlClient.SqlMethodCall'.

+0

您的問題還不是很清楚(我反正) - 什麼表格你指的是?這是Linq到實體還是Linq到對象?更有意義的屬性和表名也可能有幫助。 – BrokenGlass 2012-04-02 02:12:33

+0

對不起,我是Linq的新手,Linq to Entities或Linq to Objects的含義是什麼? – user990635 2012-04-02 02:13:45

+0

您的錯誤消息表明您使用Linq到SQL - 這就是您訪問數據庫的方式 – BrokenGlass 2012-04-02 02:15:17

回答

41

你必須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() }) 
+0

很好的答案,謝謝 – EgyEast 2016-12-04 13:51:47

+0

我只是想確定一下,所以它迭代Enumerable兩次,不是嗎?首先,在'.AsEnumerable()'之前,其次,在'.AsEnumerable()'之後? – 2017-04-11 12:17:00

8

你要拆呢分成兩個陳述。從查詢中返回結果(這將是數據庫中的結果),然後在單獨的步驟中第二次枚舉結果以將轉換轉換爲新的對象列表。這第二個「查詢」不會觸及數據庫,因此您可以在其中使用someMethod()。因爲它使轉換到從C#查詢數據庫非常無縫:但是你總是要提醒自己,「這個C#將被轉換成一些SQL 「。結果,你必須問自己:「所有這些C#實際上都可以作爲SQL執行嗎?」如果它不能 - 如果你在裏面調用someMethod() - 你的查詢會有問題。通常的解決方案是分解它。

(從@BrokenGlass對方回答,使用.AsEnumerable(),基本上是另一種方式來做到這一點。)

0

這是一個老問題,但我看到沒有人提到一個「黑客」,允許cal l選擇過程中沒有重複的方法。想法是使用構造函數,並在構造函數中,你可以調用任何你想要的(至少它在NHibernate的LINQ中工作正常,不知道LINQ2SQL或EF,但我想它應該是相同的)。 下面我有基準程序的源代碼,它看起來像在我的情況下重申的方法比構造方法慢兩倍,我想這不奇怪 - 我的業務邏輯是最小的,所以像迭代和內存分配的事情很重要。

我也希望有更好的方式說,這個或那個不應該嘗試在數據庫中執行,

// 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(); 
    } 
}