[Linq雜記] C# Lambda Join 與 Left Join 那幾招

 紀錄Lambda Join 與 Left Join 的幾個範例

發現還有SelectMany之前沒用過

真是孤陋寡聞

前置作業建立測試資料
    class GoodsInfo
    {
        public int GoodsId { get; set; } 
        public string GoodsName { get; set; } 
        public int Price { get; set; } 
    }
    class Order
    {
        public int OrderId { get; set; }
        public int GoodsId { get; set; }
        public int Quantity { get; set; }
    }

    class FullInfo
    {
        public Order _order { get; set; }
        public GoodsInfo _goods { get; set; }
    }
    class SeedData
    {
        public SeedData()
        {
            this.GenerateGoodsInfos = new List<GoodsInfo>();
            this.GenerateGoodsInfos.Add(new GoodsInfo() {
                 GoodsId = 0,
                 GoodsName = "紅茶",
                 Price = 30
            });
            this.GenerateGoodsInfos.Add(new GoodsInfo()
            {
                GoodsId = 1,
                GoodsName = "綠茶",
                Price = 30
            });
            this.GenerateGoodsInfos.Add(new GoodsInfo()
            {
                GoodsId = 2,
                GoodsName = "奶茶",
                Price = 40
            });
            this.GenerateGoodsInfos.Add(new GoodsInfo()
            {
                GoodsId = 3,
                GoodsName = "珍奶",
                Price = 50
            });
            this.GenerateGoodsInfos.Add(new GoodsInfo()
            {
                GoodsId = 4,
                GoodsName = "鮮奶茶",
                Price = 55
            });

            this.GenerateOrders = new List<Order>();

            this.GenerateOrders.Add(new Order() {
                 OrderId = 0,
                 GoodsId = 4,
                 Quantity = 3
            });
            this.GenerateOrders.Add(new Order()
            {
                OrderId = 1,
                GoodsId = 2,
                Quantity = 5
            });
            this.GenerateOrders.Add(new Order()
            {
                OrderId = 2,
                GoodsId = 0,
                Quantity = 7
            });
            this.GenerateOrders.Add(new Order()
            {
                OrderId = 3,
                GoodsId = 7,
                Quantity = 99
            });
            this.GenerateOrders.Add(new Order()
            {
                OrderId = 4,
                GoodsId = 9,
                Quantity = 99
            });

        }
        public List<GoodsInfo> GenerateGoodsInfos { get; set; }
        public List<Order> GenerateOrders { get; set; }
    }
正片開始
    class Program
    {
        static void Main(string[] args)
        {
            SeedData seedData = new SeedData();
            //JOIN
            IEnumerable<FullInfo> fullInfosJoin = seedData.GenerateOrders
                .Join(
                    seedData.GenerateGoodsInfos,
                    order=>order.GoodsId,
                    goods=>goods.GoodsId,
                    (order, goods) => 
                        new FullInfo { _order = order, _goods= goods }
                );
            Console.WriteLine("\n---JOIN---");
            foreach (var item in fullInfosJoin)
            {
                Console.WriteLine(JsonConvert.SerializeObject(item));
            }

            //----------------------------分隔線---------------------------
            //LEFT JOIN
            IEnumerable<FullInfo> fullInfosLeftJoin 
               = seedData.GenerateOrders
               .GroupJoin(
               seedData.GenerateGoodsInfos,
                   order => order.GoodsId,
                   goods => goods.GoodsId,
                   (order, goods) => new { _order = order, _goods = goods })
                   .Select(x => 
                       new FullInfo { 
                         _order = x._order, 
                         _goods = x._goods.FirstOrDefault() 
                       }
                );
            Console.WriteLine("\n---LEFT JOIN---");
            foreach (var item in fullInfosLeftJoin)
            {
                Console.WriteLine(JsonConvert.SerializeObject(item));
            }

            //----------------------------分隔線---------------------------

            //LEFT JOIN 使用 SelectMany 把_goods的資料攤平
            //參考: https://dotblogs.com.tw/mileslin/2016/03/01/015739
            IEnumerable<FullInfo> fullInfosLeftJoinSelectMany 
                = seedData.GenerateOrders
                .GroupJoin(
                seedData.GenerateGoodsInfos,
                    order => order.GoodsId,
                    goods => goods.GoodsId,
                    (order, goods) => 
                        new { _order = order, _goods = goods }
                ).SelectMany(x => 
                    x._goods.DefaultIfEmpty(),
                    (o,g) => 
                        new FullInfo {  _order = o._order, _goods = g}
                );

            Console.WriteLine("\n---LEFT JOIN 使用 SelectMany---");
            foreach (var item in fullInfosLeftJoinSelectMany)
            {
                Console.WriteLine(JsonConvert.SerializeObject(item));
            }

            Console.ReadKey();
        }
    }
輸出結果

備註