#region Imported Libraries using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; using System.Linq.Expressions; using System.Data.Objects.DataClasses; using Org.TechA.Data.Dsl; using Org.TechAvalanche.Orm.Specification; #endregion #region Namespace Declaration namespace Org.TechA.Data.Dsl2 { #region Imported Libraries using Org.TechA.Data.Dsl; using LangDomain = Org.TechA.Data.Dsl.Domain; using System.Collections; #endregion #region Root Language Type (NorthwindLangQuery Class Declaration) public class NorthwindLang { } #endregion #region Extension Methods Static Class public static class NorthwindLangQuery { #region Private Members static IEnumerable _rootQuery; static Specification _customerSpec = null; static Specification _orderSpec = null; static Specification _orderLineSpec = null; #endregion #region Start And End Tokens public static NorthwindLang BeginQuery() { _customerSpec = new Specification(c => c == c); _orderSpec = new Specification(o => o == o); _orderLineSpec = new Specification(ol => ol == ol); return new NorthwindLang(); } public static NorthwindLang EndQuery(this NorthwindLang query) { return query; } public static IEnumerable EndCustomerQuery(this Specification customers) { return DomainQuery.CreateQuery(_customerSpec, _orderSpec); } public static IEnumerable EndCustomerQuery(this Specification orders) { return DomainQuery.CreateQuery(_customerSpec, _orderSpec); } public static IEnumerable EndOrderQuery(this Specification orders) { return DomainQuery.CreateQuery(_customerSpec, _orderSpec);; } #endregion #region Printing Expressions public static void Flatten_And_Print_To_Console_Window(this IEnumerable customers) { var ols = from c in customers from o in c.Orders from ol in o.Order_Details select new { CustomerID = c.CustomerID, OrderID = ol.OrderID, ProductID = ol.ProductID, UnitPrice = ol.UnitPrice }; foreach (var flat in ols) { Console.WriteLine(string.Format("Customer ID {0} with Order ID {1} \n\r\t Line Item = Product ID {2} @ {3} ", flat.CustomerID, flat.OrderID, flat.ProductID, flat.UnitPrice)); } } public static void Print_Customer_Orders_To_Console_Window(this IEnumerable customers) { string tempCustId = default(string); foreach(var cust in customers) { if(cust.CustomerID != tempCustId) { Console.WriteLine("Order ID: " + cust.CustomerID); tempCustId = cust.CustomerID; } foreach(var order in cust.Orders) { Console.WriteLine("\t" + order.OrderID); foreach(var line in order.Order_Details) { Console.WriteLine(string.Format("\t\tProduct ID {0} x {1} units @ total cost = {2}", line.ProductID, line.Quantity, (line.Quantity * line.UnitPrice) - Convert.ToDecimal(line.Discount))); } } } } #endregion #region Root Expressions public static Specification Customers(this NorthwindLang query) { return _customerSpec; } public static Specification Orders(this NorthwindLang query) { return _orderSpec; } #endregion #region Customer Expressions public static Specification With_An_Id_Equal_To (this Specification customers, string id) { var cust_id_spec = new Specification(c => c.CustomerID == id); _customerSpec &= cust_id_spec; return _customerSpec; } public static Specification With_Orders_Shipped_From (this Specification customers, string country) { Specification order_shipcountry_spec = new Specification(o => o.ShipCountry == country); _orderSpec &= order_shipcountry_spec; return _orderSpec; } public static IEnumerable As_Unique_Where (this IEnumerable customers, Expression> whereExpression) { return customers.Distinct(new CustomerEqualityComparer(whereExpression)); } public static IEnumerable As_Unique_Where_Customers_Ids_Are_The_Same (this IEnumerable customers) { return customers.Distinct( new CustomerEqualityComparer( (left, right) => left.CustomerID == right.CustomerID)); } #endregion #region Order Expressions public static Specification That (this Specification orders) { return _orderSpec; } public static Specification Are (this Specification orders) { return _orderSpec; } public static Specification With (this Specification orders) { return _orderSpec; } public static Specification Older_In_Years_By (this Specification orders, int age) { var date = DateTime.Now.AddYears(-age); Specification order_older_spec = new Specification(o => o.OrderDate < date); return _orderSpec &= order_older_spec; } public static Specification Freight_Costs_More_Than (this Specification orders, decimal cost) { Specification order_freight_cost_spec = new Specification(o => o.Freight > cost); return _orderSpec &= order_freight_cost_spec; } #endregion } #endregion #region LINQ TO Entities Query Building Class (Factory / Decorator) class DomainQuery where T : LangDomain.IDomainEntity { #region Private Members static IEnumerable _rootQuery = null; static NorthwindEntities ctx = new NorthwindEntities(); #endregion #region Factory Methods internal static IEnumerable CreateQuery(Specification customerSpec, Specification orderSpec) { if (typeof(T) == typeof(LangDomain.Customer)) { return BuildCustomerQueryAsRootQuery(customerSpec, orderSpec); } else if (typeof(T) == typeof(LangDomain.Order)) { return BuildOrderQueryAsRootQuery(orderSpec, customerSpec); } else if (typeof(T) == typeof(LangDomain.OrderLine)) { throw new NotImplementedException("Not yet able to Create a query for Order Lines"); } else { throw new NotImplementedException( string.Format("Not yet able to Create a query for {0}", typeof(T).Name)); } } private static IEnumerable BuildOrderQueryAsRootQuery(Specification orderSpec, Specification customerSpec) { return (IEnumerable) from o in ctx.OrderSet.Where(orderSpec.EvalPredicate) join c in ctx.Customers.Where(customerSpec.EvalPredicate) on o.Customer.CustomerID equals c.CustomerID select new LangDomain.Order { OrderID = o.OrderID, EmployeeID = o.EmployeeID, CustomerReference = new LangDomain.Customer() { CustomerID = c.CustomerID, Address = c.Address, City = c.City, CompanyName = c.CompanyName, ContactName = c.ContactName, ContactTitle = c.ContactTitle, Country = c.Country, CustType = c.CustType, Fax = c.Fax, Phone = c.Phone, PostalCode = c.PostalCode, Region = c.Region }, Freight = o.Freight, OrderDate = o.OrderDate, RequiredDate = o.RequiredDate, ShipAddress = o.ShipAddress, ShipCity = o.ShipCity, ShipCountry = o.ShipCountry, ShipName = o.ShipName, ShippedDate = o.ShippedDate, ShipPostalCode = o.ShipPostalCode, ShipRegion = o.ShipRegion, ShipVia = o.ShipVia, Order_Details = from ordline in o.Order_Details select new LangDomain.OrderLine() { OrderID = ordline.OrderID, Discount = ordline.Discount, ProductID = ordline.ProductID, Quantity = ordline.Quantity, UnitPrice = ordline.UnitPrice } }; } private static IEnumerable BuildCustomerQueryAsRootQuery(Specification customerSpec, Specification orderSpec) { return (IEnumerable) from c in ctx.Customers.Where(customerSpec.EvalPredicate) join o in ctx.OrderSet.Where(orderSpec.EvalPredicate) on c.CustomerID equals o.Customer.CustomerID //join ol in ctx.OrderLineSet //on o.OrderID equals ol.OrderID orderby o.OrderID select new LangDomain.Customer() { CustomerID = c.CustomerID, Address = c.Address, City = c.City, CompanyName = c.CompanyName, ContactName = c.ContactName, ContactTitle = c.ContactTitle, Country = c.Country, CustType = c.CustType, Fax = c.Fax, Phone = c.Phone, PostalCode = c.PostalCode, Region = c.Region, Orders = from ord in c.Orders where ord.Customer.CustomerID == c.CustomerID && ord.OrderID == o.OrderID select new LangDomain.Order { OrderID = ord.OrderID, EmployeeID = ord.EmployeeID, Freight = ord.Freight, OrderDate = ord.OrderDate, RequiredDate = ord.RequiredDate, ShipAddress = ord.ShipAddress, ShipCity = ord.ShipCity, ShipCountry = ord.ShipCountry, ShipName = ord.ShipName, ShippedDate = ord.ShippedDate, ShipPostalCode = ord.ShipPostalCode, ShipRegion = ord.ShipRegion, ShipVia = ord.ShipVia, Order_Details = from line in ctx.OrderLineSet where line.OrderID == o.OrderID && o.Customer.CustomerID == c.CustomerID select new LangDomain.OrderLine { OrderID = line.OrderID, Discount = line.Discount, ProductID = line.ProductID, Quantity = line.Quantity, UnitPrice = line.UnitPrice } } }; } #endregion #region Entity Type Converters private static LangDomain.Customer CustomerConverter(Customer customer) { return new LangDomain.Customer() { Address = customer.Address, City = customer.City, CompanyName = customer.CompanyName, ContactName = customer.ContactName, ContactTitle = customer.ContactTitle, Country = customer.Country, CustomerID = customer.CustomerID, CustType = customer.CustType, Fax = customer.Fax, Phone = customer.Phone, PostalCode = customer.PostalCode, Region = customer.Region }; } private static LangDomain.Order OrderConverter(Order order) { return new LangDomain.Order() { EmployeeID = order.EmployeeID, Freight = order.Freight, OrderDate = order.OrderDate, OrderID = order.OrderID, RequiredDate = order.RequiredDate, ShipAddress = order.ShipAddress, ShipCity = order.ShipCity, ShipCountry = order.ShipCountry, ShipName = order.ShipName, ShippedDate = order.ShippedDate, ShipPostalCode = order.ShipPostalCode, ShipRegion = order.ShipRegion, ShipVia = order.ShipVia }; } #endregion } #endregion #region IEqualityComparer Classes internal class CustomerEqualityComparer : IEqualityComparer { Expression> equalsLambda = null; public CustomerEqualityComparer(Expression> compareLamba) { equalsLambda = compareLamba; } #region IEqualityComparer Members public bool Equals(LangDomain.Customer x, LangDomain.Customer y) { return equalsLambda.Compile()(x, y); } public int GetHashCode(Org.TechA.Data.Dsl.Domain.Customer obj) { return obj.ToString().GetHashCode(); } #endregion } #endregion } #endregion