Friday 19 October 2018

C# - IEnumerable++ Linq, Lambdas, AsQueryable

So in the previous post I wrote a Linq query against the IEnumerable enabled Customers class. In that post I showed the Non-Public members and wanted to replicate them. I am glad to give here some code with replicates the original Line query.

It turns out according to this SO answer that there are two ways of using LINQ expressions, you have to use either Lambda expression or SQL-Like expression

The Original "SQL" Linq Query
Customers custs = new Customers();
var query = from Customer c in custs where c.Country != "Mexico" select new { c.CustomerId, c.CustomerName };
The Linq Query Re-Expressed With Lambdas
Customers custs = new Customers();
var query2 = custs.AsQueryable().Where(c => c.Country != "Mexico").Select((c) => new { c.CustomerId, c.CustomerName });

Inspecting the variable query shows the same Non-Public members are shown in previous post.

AsQueryable

So I named this series of posts as IEnumerable++. It seems IQueryable++ may now seem more appropriate. The hop from IEnumerable to IQueryable is achieved by the Queryable.AsQueryable method. That is the magic method that takes us away from the SQL-like syntax to the Lambda syntax.

Links

Latest Source

So this source code is evolving, I have separated and commented out the Orders class for tidiness. It remains a console program. I will need the Orders class when I introduce joins.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

using System.Dynamic;
using System.Linq.Dynamic;   // Install-Package 'System.Linq.Dynamic' NuGet
using System.Linq.Expressions;

namespace ConsoleEnumTut01
{
    class Program
    {
        static void Main(string[] args)
        {
            Customers custs = new Customers();
            var query = from Customer c in custs where c.Country != "Mexico" select new { c.CustomerId, c.CustomerName };

            foreach (var customer in query)
            {
                Console.WriteLine(customer.GetType().ToString());
                Console.WriteLine(customer);
            }
            LinqWithLambdas();
        }

        static void LinqWithLambdas()
        {
            Customers custs = new Customers();
            var query2 = custs.AsQueryable().Where(c => c.Country != "Mexico").Select((c) => new { c.CustomerId, c.CustomerName });

            foreach (var customer in query2)
            {
                Console.WriteLine(customer.GetType().ToString());
                Console.WriteLine(customer);
            }
        }
    }

    class Customer
    {
        public int CustomerId { get; set; } // key field, unique identifier
        public string CustomerName { get; set; }
        public string ContactName { get; set; }
        public string Country { get; set; }
        public override string ToString() { return String.Format("{0} {1}", CustomerId, CustomerName); /* simple for now */ }
    }

    class Customers : IEnumerable<Customer>, IEnumerator<Customer>
    {
        // private members
        List<Customer> _customers;
        int _cursor;

        // constructors
        public Customers()
        {
            // delegate to Factory
            _customers = CustomersListFactory.CreateCustomers();
            _cursor = -1;
        }

        //
        // Interfaces explicitly implemented
        //

        // IEnumerable<>
        IEnumerator<Customer> IEnumerable<Customer>.GetEnumerator()
        {
            return this;
        }

        // IEnumerable
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this;
        }


        // IEnumerator, IEnumerator<>
        Customer IEnumerator<Customer>.Current => _customers[_cursor];

        object IEnumerator.Current => _customers[_cursor];

        bool IEnumerator.MoveNext()
        {
            _cursor++;
            return (_cursor < _customers.Count);
        }

        void IEnumerator.Reset()
        {
            _cursor = -1;
        }

        // IDisposable
        void IDisposable.Dispose()
        {

        }
    }

    static class CustomersListFactory
    {
        public static List<Customer> CreateCustomers()
        {
            List<Customer> customers = new List<Customer>();
            customers.Add(new Customer { CustomerId = 1, CustomerName = "Big Corp", ContactName = "Mandy", Country = "USA" });
            customers.Add(new Customer { CustomerId = 2, CustomerName = "Medium Corp", ContactName = "Bob", Country = "Canada" });
            customers.Add(new Customer { CustomerId = 3, CustomerName = "Small Corp", ContactName = "Jose", Country = "Mexico" });
            return customers;
        }
    }

    /*
    class Order
    {
        public int OrderId { get; set; }
        public int CustomerId { get; set; }
        public DateTime OrderDate { get; set; }
        public override string ToString() { return String.Format("{0} {1} {2}", OrderId, CustomerId, OrderDate);  }
    }





    static class OrdersListFactory
    {
        public static List<Order> CreateOrders()
        {
            List<Order> orders = new List<Order>();
            orders.Add(new Order { OrderId = 420, CustomerId = 2, OrderDate = new DateTime(2018, 10, 10) });
            orders.Add(new Order { OrderId = 421, CustomerId = 3, OrderDate = new DateTime(2018, 10, 11) });
            orders.Add(new Order { OrderId = 422, CustomerId = 1, OrderDate = new DateTime(2018, 10, 12) });
            orders.Add(new Order { OrderId = 423, CustomerId = 2, OrderDate = new DateTime(2018, 10, 13) });
            return orders;
        }
    }

    class Orders : IEnumerable<Order>, IEnumerator<Order>
    {
        // private members
        List<Order> _orders;
        int _cursor;

        // constructors
        public Orders()
        {
            // delegate to Factory
            _orders = OrdersListFactory.CreateOrders();
            _cursor = -1;
        }

        //
        // Interfaces explicitly implemented
        //

        // IEnumerable<>
        IEnumerator<Order> IEnumerable<Order>.GetEnumerator()
        {
            return this;
        }

        // IEnumerable
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this;
        }


        // IEnumerator, IEnumerator<>
        Order IEnumerator<Order>.Current => _orders[_cursor];

        object IEnumerator.Current => _orders[_cursor];

        bool IEnumerator.MoveNext()
        {
            _cursor++;
            return (_cursor < _orders.Count);
        }

        void IEnumerator.Reset()
        {
            _cursor = -1;
        }

        // IDisposable
        void IDisposable.Dispose()
        {

        }
    }
*/
}

No comments:

Post a Comment