來個LINQ to SQL機車考題。

有一SQL資料表如下:

請問,若不用DataContext.ExecuteQuery(),有無可能使用LINQ語法轉換出如下的SQL指令?

SELECT COUNT(*) FROM Member
WHERE RegTime < GETDATE() AND
REVERSE(UserName) = Code

我本來一直以為這種夾雜T-SQL函數的查詢條件,ExecuteQuery應是唯一解。今天查到一篇神奇的文章,才知道原來透過FunctionAttribute宣告,要搞出以下的LINQ寫法也是可能的:

var q = from o in db.Members
            where o.RegTime > db.GetDate() &&
            db.Reverse(o.UserName) == o.Code
            select o;

方法是加外新增一個cs檔案,在其中宣告DataContext的partial class,加入以下兩個Method:

using System;
using System.Data.Linq.Mapping;
using System.Reflection;
 
namespace LinqTestBed
{
    partial class PlayGroundDataContext : System.Data.Linq.DataContext
    {
        //REF: http://bit.ly/9l6LDz
        [Function(Name = "GetDate", IsComposable = true)]
        public DateTime GetDate()
        {
            MethodInfo mi = MethodBase.GetCurrentMethod() as MethodInfo;
            return (DateTime)this.ExecuteMethodCall(this, mi, 
                new object[] { }).ReturnValue;
        }
 
        [Function(Name = "Reverse", IsComposable = true)]
        public string Reverse(string str)
        {
            MethodInfo mi = MethodBase.GetCurrentMethod() as MethodInfo;
            return (string)this.ExecuteMethodCall(this, mi, 
                new object[] { str }).ReturnValue;
        }
    }
}

如此,上述LINQ語法就會被轉換以下的T-SQL指令,很酷吧!!

SELECT * AS [value]
FROM [dbo].[Member] AS [t0]
WHERE ([t0].[RegTime] > GetDate()) AND (Reverse([t0].[UserName]) = [t0].[Code])
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926

Comments

# by hectorlee369

缺點是每次要re-gen時,code都會消失 ... 好在有版控, 所以花點時間copy回來即可

# by Jeffrey

to hectorlee369, 上述的Code並不是加在自動產生的*.designer.cs裡,而是另外新增一個.cs,用partial class的方法加掛這兩個方法,這樣就不用怕re-gen時Code會消失囉!

# by jlin0502

您好, 在下新增一個.cs的檔案後. 在compile時會出現 "'System.Data.Linq.DataContext' 不包含使用 '0' 引數的建構函式" 錯誤. 不曉得問題出在哪裡呢?該如何解決?

# by Jeffrey

to jlin0502, 該錯誤的英文原文是"System.Data.Linq.DataContext' does not contain a constructor that takes '0' arguments",查了一下類似的案例,我猜是你在宣告class PlayGroundDataContext加入額外方法時,忘了加上"partial"關鍵字所造成的。

Post a comment