LINQ to SQL内での関数の使用

こんにちは、こだかです。

今回は、LINQ to SQL構文内部での関数の使用について書いておきます。
例として以下をご覧ください。

        static void Main(string[] args)
        {
            using (pubsDataContext pubs = new pubsDataContext())
            {
                pubs.Log = Console.Out;

                var titles = from t in pubs.titles
                             where t.type == Test("business")
                             select t;

                foreach (var title in titles) Console.WriteLine(title.title_id);
            }
        }

        static string Test(string arg1)
        {
            return arg1;
        }

この例は問題なく動作します。
しかし、以下のようにすると、初めてのforeachのタイミングでエラーになります。
        static void Main(string[] args)
        {
            using (pubsDataContext pubs = new pubsDataContext())
            {
                pubs.Log = Console.Out;

                var titles = from t in pubs.titles
                             where Test(t.type) == "business"
                             select t;

                foreach (var title in titles) Console.WriteLine(title.title_id);
            }
        }

        static string Test(string arg1)
        {
            return arg1;
        }

これは、LINQ to SQLの遅延実行により、初めてforeachに差し掛かったタイミングで、サポートされない関数が指定されたからです。
このように、LINQ to SQLの構文自体に独自関数を適用することは出来ないと言うことになります。

では、もう少し複雑な条件で抽出したい場合はというと、要はもともと持っているメンバーでと言う話ですね。
いくつか例を書いておきます。

含まれた文字での比較
        static void Main(string[] args)
        {
            using (pubsDataContext pubs = new pubsDataContext())
            {
                pubs.Log = Console.Out;

                var titles = from t in pubs.titles
                             where t.type.Contains("b")
                             select t;

                foreach (var title in titles) Console.WriteLine(title.title_id);
            }
        }

日付に対して年での比較
        static void Main(string[] args)
        {
            using (pubsDataContext pubs = new pubsDataContext())
            {
                pubs.Log = Console.Out;

                var titles = from t in pubs.titles
                             where t.pubdate.Year < 1999
                             select t;

                foreach (var title in titles) Console.WriteLine(title.title_id + " " + title.pubdate);
            }
        }

文字列部分比較
        static void Main(string[] args)
        {
            using (pubsDataContext pubs = new pubsDataContext())
            {
                pubs.Log = Console.Out;

                var titles = from t in pubs.titles
                             where t.type.Substring(2,2) == "si"
                             select t;

                foreach (var title in titles) Console.WriteLine(title.title_id);
            }
        }

実行してみるとわかりますが、実際にSQL Serverに発行されたSQL文で使用されたTransactSQLの関数は、
上から、LIKE、DATEPART、SUBSTRINGです。(賢いですね)

ちなみに、LINQ to Objectはこの限りではありませんので、ご注意下さい。

こだかたろう