C# LINQ to SQL で Distinct して OrderBy する

LINQ to SQL で Distinct(重複する値を削除) して OrderBy(並び替え) する方法について説明しています。

LINQ to SQL に限らず、データベースを使用していて Distinct(重複する値を削除) と OrderBy(並び替え)を同時に併用すると上手く動作しない場合があります。

LINQ to SQL の場合は下のように確実に Distinct(重複する値を削除) → OrderBy(並び替え) の順に実行されるように記述することで、期待通りの結果が得られます。

            // SQL文をデバッグ出力する為の設定
            dc.Log = new DebugWriter();
             
            // Distinct して OrderBy する
            var q = (from e in dc.EmployeeTable
                        from g in dc.GroupTable.Where(x => x.GroupCode == e.GroupCode).DefaultIfEmpty()
                        select new
                        {
                            e.UserName,
                            e.GroupCode,
                            g.GroupName,
                        }).Distinct().OrderBy(x => x.UserName);
             
            foreach (var x in q)
            {
                Console.WriteLine(string.Format("{0} : {1}", x.UserName, x.GroupCode));
            }
             
            // この時のSQLクエリは下記の通り
            // SELECT [t3].[UserName], [t3].[GroupCode], [t3].[value] AS [GroupName]
            // FROM (
            //     SELECT DISTINCT [t2].[UserName], [t2].[GroupCode], [t2].[value]
            //     FROM (
            //         SELECT [t0].[UserName], [t0].[GroupCode], [t1].[GroupName] AS [value]
            //         FROM [dbo].[EmployeeTable] AS [t0]
            //         LEFT OUTER JOIN [dbo].[GroupTable] AS [t1] ON [t1].[GroupCode] = [t0].[GroupCode]
            //         ) AS [t2]
            //     ) AS [t3]
            // ORDER BY [t3].[UserName]

なお、上のサンプルのように LINQ to SQL で実際に生成されているSQL文を確認する場合、下のようなクラスを定義して、データコンテキストの Log プロパティにセットしておくことでデバッグウィンドウに出力されます。

        /// <summary>
        /// LINQ to SQL により生成されるSQL文をデバッグ出力するためのクラス
        /// </summary>
        public class DebugWriter : System.IO.TextWriter
        {
            public override System.Text.Encoding Encoding
            {
                get { return null; }
            }
 
            public override void WriteLine(string value)
            {
                System.Diagnostics.Debug.WriteLine(value);
            }
        }
参考:LINQ to SQL で LEFT OUTER JOIN をシンプル記述する
使用環境: Visual Studio 2010 .NET Framework 3.0 以降

C# メニューリスト