41
LINQ to SQL in C# Introduction This article provides an introduction to employing LINQ to SQL within a Windows Forms application; the article will address the incorporation of LINQ to SQL into a win forms project, how to use LINQ to SQL to select, insert, update, and delete data, and how to use LINQ to SQL to execute stored procedures. Select query examples will demonstrate ordering, filtering, aggregation, returning typed lists, returning single objects and values, and how to query across entity sets (which are essentially related tables associated by foreign keys). Figure 1: Application Main Form The demonstration project included with the article is a simple win forms application; this example contains a datagridview control and a menu; the menu is used to execute each example query contained in the demonstration. The application provides the following functionality: Return Full Tables Return Typed Lists Return Single Typed Values Insert Data Update Data Delete Data Execute Stored Procedures Select Filtered Lists Select Ordered Lists Perform Aggregate Functions There is a great deal more that one can do with LINQ to SQL that is not contained in this demonstration however, the demonstration was geared towards

Linq to sql in c#

Embed Size (px)

DESCRIPTION

Linq to sql in c#

Citation preview

Page 1: Linq to sql in c#

LINQ to SQL in C#

Introduction

This article provides an introduction to employing LINQ to SQL within a Windows Forms application; the article will address the incorporation of LINQ to SQL into a win forms project, how to use LINQ to SQL to select, insert, update, and delete data, and how to use LINQ to SQL to execute stored procedures.  Select query examples will demonstrate ordering, filtering, aggregation, returning typed lists, returning single objects and values, and how to query across entity sets (which are essentially related tables associated by foreign keys).

Figure 1:  Application Main Form

The demonstration project included with the article is a simple win forms application; this example contains a datagridview control and a menu; the menu is used to execute each example query contained in the demonstration.

The application provides the following functionality:

Return Full Tables Return Typed Lists Return Single Typed Values Insert Data Update Data Delete Data Execute Stored Procedures Select Filtered Lists Select Ordered Lists Perform Aggregate Functions

There is a great deal more that one can do with LINQ to SQL that is not contained in this demonstration however, the demonstration was geared towards the mechanics of performing the most typical types of queries that might be required within a data driven application.

LINQ to SQL Statements

This section will discuss some of the common techniques used in LINQ to SQL statement construction.  In a nutshell, LINQ to SQL provides the developer with the means to conduct

Page 2: Linq to sql in c#

queries against a relational database through a LINQ to SQL database model and related data context. 

Data Context

The data context provides the mapping of all entities (essentially tables) to the database.  It is through the data context that the application can query the database and it is through the data context that changes to the database can be executed.

Anatomy of LINQ to SQL Statements

Example 1 � A Simple Select

This is an example of a very simple LINQ to SQL statement:

public void SimpleQuery(){    DataClasses1DataContext dc = new DataClasses1DataContext();     var q =        from a in dc.GetTable<Order>()        select a;     dataGridView1.DataSource = q;}

In the example, an instance of the data context is created and then a query is formed to get all of the values in the table; once the query runs, the result is used as the data source of a datagridview control and the results are displayed in the grid:

var q =        from a in dc.GetTable<Order>()        select a;

Since the Get Table function in the data context returns the entire table, this query is pretty useless but it does work and it is representative of a simple select query.  You could accomplish the same task using this code:

public void SimpleQuery2(){    DataClasses1DataContext dc = new DataClasses1DataContext();    dataGridView1.DataSource = dc.GetTable<Order>();}

If you were to create a project, add either bit of code to a method and run it, the results would look like this:

Page 3: Linq to sql in c#

Figure 2:  Query Results

Example 2 � Select with a Where Clause

The next example shows a LINQ to SQL query that incorporates a where clause.  In this example, we get a data context to work with first, and then query the Orders table to find a customer with the customer ID of starts with the letter "A", the results are then bound to a datagridview control.

public void SimpleQuery3(){    DataClasses1DataContext dc = new DataClasses1DataContext();     var q =        from a in dc.GetTable<Order>()        where a.CustomerID.StartsWith("A")        select a;     dataGridView1.DataSource = q;}

If you were to run the query, the results would appear as follows:

Page 4: Linq to sql in c#

Figure 3:  Query Results

Example 3 � Select with a Where Clause

In a slight variation to the previous query, this example looks for an exact match in its where clause:

public void SimpleQuery3(){    DataClasses1DataContext dc = new DataClasses1DataContext();     var q =        from a in dc.GetTable<Order>()        where a.CustomerID == "VINET"        select a;     dataGridView1.DataSource = q;}

Running this code will display this result:

Page 5: Linq to sql in c#

Figure 4:  Query Results

Example 4 � Generating an Ordered List

In this query, the list of orders is ordered (using "orderby a.OrderDate ascending"):

public void SimpleQuery5(){    DataClasses1DataContext dc = new DataClasses1DataContext();     var q =        from a in dc.GetTable<Order>()        where a.CustomerID.StartsWith("A")        orderby a.OrderDate ascending        select a;     dataGridView1.DataSource = q;}

 Figure 5:  Query Results

Example 5 � Working with a Custom Type

In this example a query is built to return a list of a custom type (CustomerOrderResult).

public void GetCustomerOrder(){    DataClasses1DataContext dc = new DataClasses1DataContext();     var q= (from orders in dc.GetTable<Order>()            from orderDetails in dc.GetTable<Order_Detail>()            from prods in dc.GetTable<Product>()            where ((orderDetails.OrderID == orders.OrderID) &&                 (prods.ProductID == orderDetails.ProductID) &&

Page 6: Linq to sql in c#

                 (orders.EmployeeID == 1))            orderby orders.ShipCountry            select new CustomerOrderResult            {                CustomerID = orders.CustomerID,                CustomerContactName = orders.Customer.ContactName,                CustomerCountry = orders.Customer.Country,                OrderDate = orders.OrderDate,                EmployeeID = orders.Employee.EmployeeID,                EmployeeFirstName = orders.Employee.FirstName,                EmployeeLastName = orders.Employee.LastName,                ProductName = prods.ProductName            }).ToList<CustomerOrderResult>();     dataGridView1.DataSource = q;}      

The "select new" in the query defines the result type and then sets each of the properties in the type to a value returned by the query.  At the end of the query, the output is converted to a List of the CustomerOrderResult type.

The displayed results of running the query are:

Figure 6:  Query Results

The CustomerOrderResult class used in as the type behind the parts list is as follows:

public class CustomerOrderResult{          public System.String CustomerID                   {get;set;}          public System.String CustomerContactName                   {get;set;}          public System.String CustomerCountry                   {get;set;}

Page 7: Linq to sql in c#

          public System.Nullable<System.DateTime> OrderDate                   {get;set;}          public System.Int32 EmployeeID                   {get;set;}          public System.String EmployeeFirstName                   {get;set;}          public System.String EmployeeLastName                   {get;set;}          public System.String ProductName                   {get;set;}} Example 6 � Searching an Existing List<T> Using LINQ to Objects

In this example, a typed list is created (as in the previous example) using LINQ to SQL, populated, and then the returned typed list is queried using LINQ to Objects.  In this case, the query includes a where clause that only returns matches were the customer ID begins is equal to "RICAR":

public void GetCustomerOrder2(){    DataClasses1DataContext dc = new DataClasses1DataContext();     var query = (from orders in dc.GetTable<Order>()             from orderDetails in dc.GetTable<Order_Detail>()             from prods in dc.GetTable<Product>()             where ((orderDetails.OrderID == orders.OrderID)                  && (prods.ProductID == orderDetails.ProductID)                  && (orders.EmployeeID == 1))             orderby orders.ShipCountry             select new CustomerOrderResult             {                 CustomerID = orders.CustomerID,                 CustomerContactName = orders.Customer.ContactName,                 CustomerCountry = orders.Customer.Country,                 OrderDate = orders.OrderDate,                 EmployeeID = orders.Employee.EmployeeID,                 EmployeeFirstName = orders.Employee.FirstName,                 EmployeeLastName = orders.Employee.LastName,                 ProductName = prods.ProductName             }).ToList<CustomerOrderResult>();     var matches = (from c in query                  where c.CustomerID == "RICAR"                  select c).ToList<CustomerOrderResult>();     dataGridView1.DataSource = matches;}

Page 8: Linq to sql in c#

Figure 7:  Query Results

Example 7 � Searching an Existing List<T> Using LINQ to Objects and Returning a Single Result

In this example, a typed list is created (as in the previous example), populated, and then queried using LINQ to Objects.  In this case, returns a single result of type "Parts":

public void GetEmployeeLastName(){    DataClasses1DataContext dc = new DataClasses1DataContext();     var query = (from orders in dc.GetTable<Order>()                 select orders);     var matches = (from c in query                   where c.OrderID == 10248                   select                   c.Employee.LastName).SingleOrDefault<System.String>();     MessageBox.Show(matches); }

The results are displayed as:

Figure 8:  Returning a Single Result

The preceding examples were intended to provide a simple overview as to how to conduct some basic queries against collections using LINQ to SQL and LINQ to Objects; there are certainly a great number of more complex operations that can be executed using similar procedures (groups and aggregation, joins, etc.) however the examples provided are representative of some of the more common types of queries.

Page 9: Linq to sql in c#

Getting Started

There is a single solution included with this download, the solution contains a Win Forms project called "L2S_Northwind"; this project contains one form (the main form used to display the results of the demonstration queries (frmMain) , and LINQ to SQL database model (NorthWindDataClasses.dbml) along with the models designer code and layout file, and a class entitled, "Accessor" which contains code used to perform the LINQ to SQL queries used in the demonstration.If you open the attached project into Visual Studio 2008; you should see the following in the solution explorer:

 Figure 9:  Solution Explorer

The demonstration relies upon an instance of the Northwind database running in SQL Server 2005.  The database can be downloaded from here (http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&displaylang=en); the database was created for SQL Server 2000 but you can install the database and attach to it using a local instance of SQL Server 2005.

Once the database is installed, you will want to update the connection string found in the project settings.  Open the settings and click on the button (showing an ellipsis) to set the connection string.

Page 10: Linq to sql in c#

 Figure 10:  Settings and the Connection String

Figure 11:  Adding LINQ to SQL Classes to a Project

When starting from scratch, in order to add LINQ to SQL to a project, open the "Add New Item" dialog and select the LINQ to SQL Classes item (Figure 11); name the data classes and then select the "Add" button to add the item to the project.  Once set, set the connection string for the data classes, then open the server explorer to drag tables and stored procedures onto the designer (dragging the tables into the left hand side of the workspace and stored procedures into the right hand side of the workspace (Figure 12)).  Once that is done, build the project to generate the LINQ to SQL code.

Page 11: Linq to sql in c#

 Figure 12: Model of Northwind Data Class (tables on left, stored procedures on right)

This project is intended for Visual Studio 2008 with the .NET framework version 3.5.

Code:  Accessor.cs

The Accessor class is used to the store all of the functions used to execute LINQ to SQL queries against the database.  The functions contained in this class are all static and include a mixed bag of selects, inserts, updates, deletes, and stored procedure evocations.  You may wish to implement some business logic in the extensibility methods defined in the auto-generated code contained in the designer file but I chose not to in this example.

The class begins with the normal and default imports:

using System;using System.Collections.Generic;using System.Linq;using System.Data.Linq;using System.Text;

The next section contains the namespace and class declarations. 

namespace L2S_Northwind{     /// <summary>    /// This class defines functions used to    /// select, insert, update, and delete data    /// using LINQ to SQL and the defined

Page 12: Linq to sql in c#

    /// data context    /// </summary>    public class Accessor    {

Next up is a region containing all of the functions used to return full tables from the database through the data context.  All of the functions work essentially the same way; the data context includes a function called GetTable<T> which is used to return a table of the indicated type.  Each example gets a data context and then evokes the GetTable function to return the full table of the indicated type.

#region  Full Table         // This section contains examples of        // pulling back entire tables from        // the database         /// <summary>        /// Displays the full Employee table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Employee> GetEmployeeTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<Employee>();        }          /// <summary>        /// Displays the full Shipper table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Shipper> GetShipperTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<Shipper>();        }         /// <summary>        /// Displays the full Order table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Order> GetOrderTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();

      return dc.GetTable<Order>();        }          /// <summary>        /// Displays the full EmployeeTerritory table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<EmployeeTerritory>

Page 13: Linq to sql in c#

        GetEmployeeTerritoryTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<EmployeeTerritory>();        }          /// <summary>        /// Displays Territory Table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Territory> GetTerritoryTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<Territory>();        }          /// <summary>        /// Displays the full Region table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Region> GetRegionTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<Region>();        }          /// <summary>        /// Displays the full Customer table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Customer> GetCustomerTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<Customer>();        }          /// <summary>        /// Displays the full CustomerCustomerDemo table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<CustomerCustomerDemo>        GetCustomerDemoTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<CustomerCustomerDemo>();        }          /// <summary>        /// Displays the full CustomerDemographic table        /// </summary>        /// <returns></returns>

Page 14: Linq to sql in c#

        public static System.Data.Linq.Table<CustomerDemographic>        GetCustomerDemographicTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<CustomerDemographic>();        }          /// <summary>        /// Displays the full Order_Detail table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Order_Detail> GetOrderDetailsTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<Order_Detail>();        }          /// <summary>        /// Displays the full Product table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Product> GetProductTable()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();            return dc.GetTable<Product>();        }          /// <summary>        /// Displays the full Supplier table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Supplier> GetSupplierTable()        {            NorthWindDataClassesDataContext dc = new                        NorthWindDataClassesDataContext();            return dc.GetTable<Supplier>();        }          /// <summary>        /// Displays the full Category table        /// </summary>        /// <returns></returns>        public static System.Data.Linq.Table<Category> GetCategoryTable()        {            NorthWindDataClassesDataContext dc = new             NorthWindDataClassesDataContext();            return dc.GetTable<Category>();        } 

#endregion

Page 15: Linq to sql in c#

That next region contained in the Accessor class is Queries region; this region contains examples of different types of select queries that may be performed using LINQ to SQL.  Each query is described in the annotation:

#region Queries         // This region contains examples of some        // of the sorts of queries that can be        // executed using LINQ to SQL         /// <summary>        /// Example:  Where Clause        /// Returns an employee where the        /// employee ID matches the value        /// passed in as empID        /// </summary>        /// <param name="empId"></param>        /// <returns>The single matching or default value</returns>        public static Employee GetEmployeeById(int empId)        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return (from e in dc.GetTable<Employee>()                    where (e.EmployeeID == empId)                    select e).SingleOrDefault<Employee>();        }         /// <summary>        /// Example:  Select to a single returned object        /// using a Where Clause        ///        /// Returns the first matching order        /// </summary>        /// <param name="orderId"></param>        /// <returns>The single matching or default value</returns>        public static Order GetOrderById(int orderId)        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return (from ord in dc.GetTable<Order>()                    where (ord.OrderID == orderId)                    select ord).SingleOrDefault<Order>();        }          /// <summary>        /// Example:  Select to a typed List        /// using a Where Clause        /// </summary>        /// <param name="orderId"></param>        /// <returns></returns>        public static List<Order> GetOrdersById(int orderId)        {            NorthWindDataClassesDataContext dc = new

Page 16: Linq to sql in c#

            NorthWindDataClassesDataContext();             return (from ord in dc.GetTable<Order>()                    where (ord.OrderID == orderId)                    select ord).ToList<Order>();        }         /// <summary>        /// Example:  Return an ordered list        ///        /// Converts the returned value to a List        /// of type Employee; the list is ordered        /// by hire date        /// </summary>        /// <returns></returns>        public static List<Employee> GetEmployeesByHireDate()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return (from emp in dc.GetTable<Employee>()                    orderby emp.HireDate ascending                    select emp).ToList<Employee>();        }          /// <summary>        /// This class is used to define the return type        /// for the next function - OrdersAndDetails        ///        /// When results are extracted from multiple tables        /// you can either return the results as anonymous        /// or as a type; this class defines the return        /// type used by OrdersAndDetails        /// </summary>        public class OrdersAndDetailsResult        {            public System.String CustomerID            { get; set; }            public System.Nullable<System.DateTime> OrderDate            { get; set; }            public System.Nullable<System.DateTime> RequiredDate            { get; set; }            public System.String ShipAddress            { get; set; }            public System.String ShipCity            { get; set; }            public System.String ShipCountry            { get; set; }            public System.String ShipZip            { get; set; }            public System.String ShippedTo            { get; set; }            public System.Int32 OrderID            { get; set; }            public System.String NameOfProduct            { get; set; }

Page 17: Linq to sql in c#

            public System.String QtyPerUnit            { get; set; }            public System.Nullable<System.Decimal> Price            { get; set; }            public System.Int16 QtyOrdered            { get; set; }            public System.Single Discount            { get; set; }        }          /// <summary>        /// Example:  Joins        /// Joining using the join keyword        ///        /// The values are set to each of the        /// properties contained in the        /// OrdersAndDetailsResult class        ///        /// The value returned is converted        /// to a list of the specified type        /// </summary>        /// <returns></returns>        public static List<OrdersAndDetailsResult> OrdersAndDetails()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return (from ords in dc.GetTable<Order>()                    join dets in dc.GetTable<Order_Detail>()                        on ords.OrderID equals dets.OrderID                    orderby ords.CustomerID ascending                        select new OrdersAndDetailsResult                        {                            CustomerID = ords.CustomerID,                            OrderDate = ords.OrderDate,                            RequiredDate = ords.RequiredDate,                            ShipAddress = ords.ShipAddress,                            ShipCity = ords.ShipCity,                            ShipCountry = ords.ShipCountry,                            ShipZip = ords.ShipPostalCode,                            ShippedTo = ords.ShipName,                            OrderID = ords.OrderID,                            NameOfProduct = dets.Product.ProductName,                            QtyPerUnit = dets.Product.QuantityPerUnit,                            Price = dets.Product.UnitPrice,                            QtyOrdered = dets.Quantity,                            Discount = dets.Discount                        }                    ).ToList <OrdersAndDetailsResult>();        }          /// <summary>        /// Defined to support following function:        /// GetOrderAndPricingInformation - this class        /// supplies the return type for that function        /// </summary>

Page 18: Linq to sql in c#

        public class OrderandPricingResult        {            public System.Int32 OrderID            { get; set; }            public System.String Company            { get; set; }            public System.String OrderCountry            { get; set; }            public System.String ProductName            { get; set; }            public System.Nullable<System.Decimal> UnitPrice            { get; set; }            public System.Int16 UnitsOrder            { get; set; }            public System.String ShipperName            { get; set; }            public System.String SalesFirstName            { get; set; }            public System.String SalesLastName            { get; set; }            public System.String SalesTitle            { get; set; }        }          /// <summary>        /// Example:  Query across an entity ref        /// This example collections information from the orders table        /// and the order_details table through the orders table        /// entity association to the orders_details table.         ///        /// An entity is a representation in the model of a table        /// in the database, foreign key relationships are maintained        /// as entity references to the related tables in the model.        /// It is possible to query across tables through this        /// relationship in LINQ to SQL        /// </summary>        /// <returns></returns>        public static List<OrderandPricingResult> GetOrderAndPricingInformation()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return (from ords in dc.Orders // orders table                    from dets in ords.Order_Details     // entity set in orders table                    select new OrderandPricingResult                    {                        OrderID = ords.OrderID,                        Company =ords.Customer.CompanyName,                          OrderCountry = ords.Customer.Country,                        ProductName = dets.Product.ProductName,                        UnitPrice = dets.Product.UnitPrice,                        UnitsOrder = dets.Quantity,                        ShipperName = ords.Shipper.CompanyName,                        SalesFirstName = ords.Employee.FirstName,                        SalesLastName = ords.Employee.LastName,                        SalesTitle = ords.Employee.Title

Page 19: Linq to sql in c#

                    }).ToList < OrderandPricingResult>();        }          /// <summary>        /// Example:  Query across entity ref with Where class        /// Same as previous function with added where clause        ///        /// An entity is a representation in the model of a table        /// in the database, foreign key relationships are maintained        /// as entity references to the related tables in the model.        /// It is possible to query across tables through this        /// relationship in LINQ to SQL        /// </summary>        /// <param name="orderId"></param>        /// <returns></returns>        public static List<OrderandPricingResult>        GetOrderAndPricingInformationByOrderId(int orderId)        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return (from ords in dc.Orders  // orders table                    from dets in ords.Order_Details // entity set in orders table                    where ords.OrderID == orderId                    select new OrderandPricingResult                    {                        OrderID = ords.OrderID,                        Company = ords.Customer.CompanyName,                        OrderCountry = ords.Customer.Country,                        ProductName = dets.Product.ProductName,                        UnitPrice = dets.Product.UnitPrice,                        UnitsOrder = dets.Quantity,                        ShipperName = ords.Shipper.CompanyName,                        SalesFirstName = ords.Employee.FirstName,                        SalesLastName = ords.Employee.LastName,                        SalesTitle = ords.Employee.Title                    }).ToList<OrderandPricingResult>();        }          /// <summary>        /// Example:  Aggregation        ///        /// Returns the total sum of the order        /// selected by order ID by selecting        /// unit price multiplied by quantity        /// ordered and then calling sum for        /// the total        /// </summary>        /// <param name="orderID"></param>        /// <returns></returns>        public static decimal? GetOrderValueByOrderId(int orderID)        {             NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext(); 

Page 20: Linq to sql in c#

            var matches =                (from od in dc.GetTable<Order_Detail>()                where od.OrderID == orderID                select od.Product.UnitPrice * od.Quantity).Sum();             return matches;                   }          /// <summary>        /// Example:  Using Take to get a limited        /// number of returned values for display and        /// using Skip to sequence to a different        /// starting point within the returned values -        /// can be used to navigate through a large        /// list        /// </summary>        /// <param name="SkipNumber"></param>        /// <returns></returns>        public static List<Order> GetTopFiveOrdersById(int SkipNumber)        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return (from ord in dc.GetTable<Order>()                    orderby ord.OrderID ascending                    select ord).Skip(SkipNumber).Take(5).ToList<Order>();        } 

#endregion

The next region is "Inserting, Updating, and Deleting Data"; it contains examples of how to insert or update data, and an example showing how to delete data from the database.  Each function is described in its annotation:

#region Inserting, Updating, Deleting Data          /// <summary>        /// Insert or Update a Customer Record        ///        /// If the customer ID exists, the existing        /// customer record is updated.        ///        /// If the customer ID does not exist, the        /// new customer record is inserted into        /// the database        /// </summary>        /// <param name="customerId"></param>        /// <param name="companyName"></param>        /// <param name="contactName"></param>        /// <param name="contactTitle"></param>        /// <param name="address"></param>        /// <param name="city"></param>        /// <param name="region"></param>        /// <param name="postalCode"></param>

Page 21: Linq to sql in c#

        /// <param name="country"></param>        /// <param name="phone"></param>        /// <param name="fax"></param>        public static void InsertOrUpdateCustomer(string customerId, string            companyName, string contactName, string contactTitle, string address,            string city, string region, string postalCode, string country, string            phone, string            fax)        {             NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             var matchedCustomer = (from c in dc.GetTable<Customer>()                                   where c.CustomerID == customerId                                   select c).SingleOrDefault();             if(matchedCustomer == null)            {                try                {                    // create new customer record since customer ID                    // does not exist                    Table<Customer> customers = Accessor.GetCustomerTable();                    Customer cust = new Customer();                     cust.CustomerID = customerId;                    cust.CompanyName = companyName;                    cust.ContactName = contactName;                    cust.ContactTitle = contactTitle;                    cust.Address = address;                    cust.City = city;                    cust.Region = region;                    cust.PostalCode = postalCode;                    cust.Country = country;                    cust.Phone = phone;                    cust.Fax = fax;                     customers.InsertOnSubmit(cust);                    customers.Context.SubmitChanges();                }                catch (Exception ex)                {                    throw ex;                }             }            else            {                try                {                    matchedCustomer.CompanyName = companyName;                    matchedCustomer.ContactName = contactName;                    matchedCustomer.ContactTitle = contactTitle;                    matchedCustomer.Address = address;                    matchedCustomer.City = city;                    matchedCustomer.Region = region;

Page 22: Linq to sql in c#

                    matchedCustomer.PostalCode = postalCode;                    matchedCustomer.Country = country;                    matchedCustomer.Phone = phone;                    matchedCustomer.Fax = fax;                     dc.SubmitChanges();                }                catch (Exception ex)                {                    throw ex;                }            }         }          /// <summary>        /// Delete a customer by customer ID        /// </summary>        /// <param name="customerID"></param>        public static void DeleteCustomer(string customerID)        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             var matchedCustomer = (from c in dc.GetTable<Customer>()                                   where c.CustomerID == customerID                                   select c).SingleOrDefault();             try            {                dc.Customers.DeleteOnSubmit(matchedCustomer);                dc.SubmitChanges();            }            catch (Exception ex)            {                throw ex;            }        } 

#endregion

The last region of the class contains the code used to execute stored procedures.  The stored procedures, once added to the project may be immediately accessed through the data context; to access a stored procedure just get an instance of the data context and call the stored procedure, passing along any required parameters as arguments to the function call:

#region Stored Procedures          /// <summary>        /// Stored Procedure:  Sales By Year        /// </summary>        /// <param name="beginningYear"></param>        /// <param name="endingYear"></param>        /// <returns></returns>

Page 23: Linq to sql in c#

        public static List<Sales_by_YearResult> SalesByYear(DateTime? beginningYear,        DateTime? endingYear)        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();                       return dc.Sales_by_Year(beginningYear,            endingYear).ToList<Sales_by_YearResult>();        }          /// <summary>        /// Stored Procedure:  Ten Most Expenisve Products        /// </summary>        /// <returns></returns>        public static List<Ten_Most_Expensive_ProductsResult>        TenMostExpensiveProducts()        {            NorthWindDataClassesDataContext dc = new            NorthWindDataClassesDataContext();             return                     dc.Ten_Most_Expensive_Products().ToList<            Ten_Most_Expensive_ProductsResult>();         } 

#endregion

That concludes the description of the "Accessor" class.

Code:  Main Application Form (frmMain.cs)

This is the main form of the application; this form is used to provide a test harness for testing each of the functions defined in the Accessor class; all functions defined in the Accessor class have a corresponding menu item and the click event handler for each menu item executes an Accessor class function; supplying any arguments necessary as canned values.

The structure for the main form's menu is as follows:

Menuo File

Exito Read

Tables Queries Stored Procedures

o Insert/Update/Delete

Page 24: Linq to sql in c#

Figure 13:  frmMain.cs

The class begins with the normal and default imports:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;

The next section contains the namespace and class declarations. 

namespace L2S_Northwind{     /// <summary>    /// This class is used to demonstrate each of the    /// queries defined in the accessor class    /// </summary>    public partial class frmMain : Form    {

Next is the definition of a private variable used to maintain the position within the orders table; it used in an example showing how to make use of the Skip and Take functions.

        // used to support take/skip example        private int OrderPosition;

Page 25: Linq to sql in c#

The next region of code in the class contains the constructor.  The constructor sets the Order Position integer value to zero.

#region Constructor         public frmMain()        {            InitializeComponent();             // set order position to zero            OrderPosition = 0;        } #endregion

The next code region is called 'Full Table Requests'.  Each of the functions operates in a similar manner in that the function creates a list of the type returned by the Accessor class function called, evokes the Accessor function and then assigns the returned list to the data source property of the datagridview control contained in the main form.

#region  Full Table Requests         private void employeesToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Employee> emp = Accessor.GetEmployeeTable();            dataGridView1.DataSource = emp;        }          private void shippersToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Shipper> ship = Accessor.GetShipperTable();            dataGridView1.DataSource = ship;        }          private void ordersToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Order> orders = Accessor.GetOrderTable();            dataGridView1.DataSource = orders;        }          private void employeeTerritoryToolStripMenuItem_Click(object sender,        EventArgs e)        {            System.Data.Linq.Table<EmployeeTerritory> empTerrs =            Accessor.GetEmployeeTerritoryTable();             dataGridView1.DataSource = empTerrs;        }          private void territoryToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Territory> terrs = Accessor.GetTerritoryTable();            dataGridView1.DataSource = terrs;        }  

Page 26: Linq to sql in c#

        private void regionToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Region> regs = Accessor.GetRegionTable();            dataGridView1.DataSource = regs;        }          private void customerToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Customer> cust = Accessor.GetCustomerTable();            dataGridView1.DataSource = cust;        }          private void customerDemoToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<CustomerCustomerDemo> custdemo =            Accessor.GetCustomerDemoTable();             dataGridView1.DataSource = custdemo;        }          private void customerDemographicToolStripMenuItem_Click(object sender,        EventArgs e)        {            System.Data.Linq.Table<CustomerDemographic> custdemograph =            Accessor.GetCustomerDemographicTable();             dataGridView1.DataSource = custdemograph;        }          private void orderDetailsToolStripMenuItem_Click(object sender,

 EventArgs e)        {            System.Data.Linq.Table<Order_Detail> ordDetails =            Accessor.GetOrderDetailsTable();                       dataGridView1.DataSource = ordDetails;        }          private void productToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Product> prods = Accessor.GetProductTable();            dataGridView1.DataSource = prods;        }          private void supplierProductToolStripMenuItem_Click(object sender,

 EventArgs e)        {            System.Data.Linq.Table<Supplier> prods = Accessor.GetSupplierTable();            dataGridView1.DataSource = prods;        }          private void categoToolStripMenuItem_Click(object sender, EventArgs e)        {            System.Data.Linq.Table<Category> cats = Accessor.GetCategoryTable();            dataGridView1.DataSource = cats;

Page 27: Linq to sql in c#

        } 

#endregion

The next region contains the menu item click event handlers used to execute each of the queries described in the queries region of the Accessor class.  Each function is annotated to describe what it does and what it is intended to demonstrate.

#region Queries          /// <summary>        /// Find and display an employee by        /// the employee's ID        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void employeeByIDToolStripMenuItem_Click(object sender, EventArgs e)        {             Employee emp = Accessor.GetEmployeeById(1);             StringBuilder sb = new StringBuilder();            sb.Append("Employee 1: " + Environment.NewLine);            sb.Append("Name: " + emp.FirstName + " " + emp.LastName +            Environment.NewLine);             sb.Append("Hire Date: " + emp.HireDate + Environment.NewLine);            sb.Append("Home Phone: " + emp.HomePhone + Environment.NewLine);             MessageBox.Show(sb.ToString(), "Employee ID Search");        }          /// <summary>        /// Gets an Order by the order ID and        /// displays information about the first        /// single matching order.        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void orderByIDToolStripMenuItem_Click(object sender, EventArgs e)        {            Order ord = Accessor.GetOrderById(10248);             StringBuilder sb = new StringBuilder();            sb.Append("Order: " + Environment.NewLine);            sb.Append("Order ID: " + ord.OrderID + Environment.NewLine);            sb.Append("Date Shipped: " + ord.ShippedDate + Environment.NewLine);            sb.Append("Shipping Address: " + ord.ShipAddress + Environment.NewLine);            sb.Append("         City: " + ord.ShipCity + Environment.NewLine);            sb.Append("         Region: " + ord.ShipRegion + Environment.NewLine);            sb.Append("         Country: " + ord.ShipCountry + Environment.NewLine);            sb.Append("         Postal Code: " + ord.ShipPostalCode +

      Environment.NewLine); 

            sb.Append("Shipping Name: " + ord.ShipName + Environment.NewLine);

Page 28: Linq to sql in c#

             MessageBox.Show(sb.ToString(), "Shipping Information");        }          /// <summary>        /// Displays a list of employeess ordered by        /// their dates of hire        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void employeesByHireDateToolStripMenuItem_Click(object sender,        EventArgs e)        {            List<Employee> emps = Accessor.GetEmployeesByHireDate();            dataGridView1.DataSource = emps;        }          /// <summary>        /// Displays all orders that match        /// on Order ID        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void ordersByIdToolStripMenuItem_Click(object sender, EventArgs e)        {            List<Order> orders = Accessor.GetOrdersById(10248);            dataGridView1.DataSource = orders;        }          /// <summary>        /// Returns values based on joining the Order and        /// Order_Details tables        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void ordersAndDetailsToolStripMenuItem_Click(object sender,        EventArgs e)        {            List<Accessor.OrdersAndDetailsResult> oad = Accessor.OrdersAndDetails();            dataGridView1.DataSource = oad;        }         /// <summary>        /// Query across entity set        /// This example collections information from the orders table        /// and the order_details table through the orders table        /// entity reference to orders_details.        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void ordersAndDetailsEntityRefToolStripMenuItem_Click(object sender,        EventArgs e)        {            List<Accessor.OrderandPricingResult> opr =            Accessor.GetOrderAndPricingInformation();            dataGridView1.DataSource = opr;

Page 29: Linq to sql in c#

        }          /// <summary>        /// Retrieves values across an entity set to        /// display both order and pricing information        /// by filtering for an order ID        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void ordersAndDetailsByOrderIDEntityRefToolStripMenuItem_Click(object        sender, EventArgs e)        {            List<Accessor.OrderandPricingResult> opr =            Accessor.GetOrderAndPricingInformationByOrderId(10248);            dataGridView1.DataSource = opr;        }          /// <summary>        /// Displays to total dollar value of the selected order        /// by multiplying each order product's unit cost by        /// the units ordered, and then summing the total of each        /// individual cost.        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void orderValueByOrderIDToolStripMenuItem_Click(object sender,        EventArgs e)        {            // get the dollar value            decimal? d = Accessor.GetOrderValueByOrderId(10248);             // convert the decimal value to currency            string dollarValue = string.Format("{0:c}", d);                       // display the dollar value            MessageBox.Show("The total dollar value of order 10248 is " +                dollarValue, "Order 10248 Value");        }          /// <summary>        /// Displays the top five orders in the order table        /// on first selection and then increments up by        /// five orders to show the list five orders        /// at a time        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void getTopFiveOrdersToolStripMenuItem_Click(object sender,        EventArgs e)        {            try            {                // get the top five orders starting at the current position                List<Order> ords = Accessor.GetTopFiveOrdersById(OrderPosition);                dataGridView1.DataSource = ords; 

Page 30: Linq to sql in c#

                // increment the formwide variable used to                // keep track of the position within the                // list of orders                OrderPosition += 5;                 // change the text in the menu strip item                // to show that it will retrieve the next                // five values after the current position                // of th last value shown in the grid                getTopFiveOrdersToolStripMenuItem.Text = "Get Next Five Orders";            }            catch            {                MessageBox.Show("Cannot increment an higher, starting list over.");                OrderPosition = 0;            }        } 

#endregion

The next region contains methods used to insert, update, or delete data from the database; these click event handlers evoke the corresponding functions contained in the Accessor class:

#region Insert Update Delete

The Insert or Update Customer menu item click event handler calls the Accessor class Insert or Update Customer function, passing in some canned arguments to populate the last.  If you look at the customer table before and after executing this click event handler you will see the customer added to the table.

private void insertOrUpdateCustomerToolStripMenuItem_Click(object sender,EventArgs e){    try    {        Accessor.InsertOrUpdateCustomer("AAAAA",

"BXSW", "Mookie Carbunkle",                    "Chieftain",                    "122 North Main Street",

"Wamucka", "DC", "78888",                    "USA", "244-233-8977",                    "244-438-2933");    }    catch (Exception ex)    {        MessageBox.Show(ex.Message, "Error");    }}

The Delete Customer menu item click event handler is used to delete the customer created by running the previous function; again, checking the table before and after running this click event handler will allow you to see the added customer deleted from the table.

Page 31: Linq to sql in c#

private void deleteCustomerToolStripMenuItem_Click(object sender,EventArgs e){    try    {        Accessor.DeleteCustomer("AAAAA");    }    catch (Exception ex)    {        MessageBox.Show(ex.Message, "Error");    }}  #endregion

The final region in this class is used to execute a couple of the stored procedures made available through the data context. 

#region Stored Procedures         /// <summary>        /// Execute stored procedure: Sales By Year        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void salesByYearToolStripMenuItem_Click(object sender, EventArgs e)        {            DateTime start = new DateTime(1990, 1, 1);            DateTime end = new DateTime(2000, 1, 1);             List<Sales_by_YearResult> result = Accessor.SalesByYear(start, end);            dataGridView1.DataSource = result;        }         /// <summary>        /// Execute stored procedure: Ten Most Expensive Products        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void tenMostExpensiveProductsToolStripMenuItem_Click(object sender,        EventArgs e)        {            List<Ten_Most_Expensive_ProductsResult> result =            Accessor.TenMostExpensiveProducts();            dataGridView1.DataSource = result;        } 

#endregion

The last region contained in the class is the housekeeping region; in this region there is only one click event handler which is used to exit the application.

#region Housekeeping

Page 32: Linq to sql in c#

         private void exitToolStripMenuItem_Click(object sender, EventArgs e)        {            Application.Exit();        } #endregion Summary

The article shows some simple examples of LINQ to SQL; from it you can see how easy it is to query against single and related tables and to write filtered queries, execute stored procedures, perform aggregation, and how to insert, update, and delete records from the database.

10 Facts about LINQ:1. Unify Progaming Model 

With the same syntax you can query Database, Objects in memory and XML files

2. Extensive syntax 

Over 50 different query methods, such as Select, OrderBy and Where...

3. Extensibility 

Using Extention methods you can extend LINQ, 

For Example, It enabled the creation of LINQ to Amazon and LINQ to Google. 

For more information see LINQ to Services Post, and Extending LINQ.

4. Deferred Execution 

Some query operator doesn't execute until you access the result 

For more information, see Examples Section

5. XML support 

With LINQ you can easily create and query XML document 

Yes LINQ is beyond just query data 

For more information, see LINQ to XML Section

6. Lambda Expression 

LINQ is one of the very common situation you will use Lambda Expression

7. Extention Methods 

LINQ standard query operators are extention methods to the IEnumerable and IQueryable

Page 33: Linq to sql in c#

interfaces That why you must using System.Linq; inorder to have those methods when you

use a List for example

8. Smart Execution 

Filter the data is executed inside the data base, which can save lots of database and

memory resources

9. IEnumerable vs IQueryable 

LINQ to object in memory uses IEnumerable 

LINQ to SQL uses IQueryable 

IQuerable rapping the lambda with Expression type, and IEnumerable uses directly Lambda

Expression 

This allows IQuerable to perform Smart Exection and to work with database.

10. Syntax suger 

Fluent syntax is complied into Query Expression syntax 

For more information visit the LINQ Examples Section

LINQ to XML TutorialLINQ to XML Tutorial shows how to create, save, load, and query xml with LINQ LINQ to XML is new simplified XML api you should familiar with 

Basic Example?

1

2

3

4

5

6

7

8

//Creating the XML document

XElement students =  new XElement("Students",

                         new XElement("Bark", 9),

                         new XElement("Mark", 6),

                         new XElement("Luck", 8));

//Saving the document (Just to demonstrate how easy is it)

students.Save(@"c:\Students.xml");

Page 34: Linq to sql in c#

9

10

11

12

13

14

15

16

17

18

19

20

//Printing the document

Console.WriteLine(students.ToString());

output:

<students>

  <bark>9</bark>

  <mark>6</mark>

  <luck>8</luck>

</students>

//The Students.xml is looking just like the output...

Dynamic Example?

1

2

3

4

5

6

7

8

9

//Defining a collection

IEnumerable<student> students = new List<student>{

                       new Student (name: "Bark", average: 9),

                       new Student (name: "Mark", average:6),

                       new Student (name: "Luck", average:8)};

                       

//Functional construction

//Creating XML document, sorted by the grades

XElement xml = new XElement("Students",

                            from s in students

Page 35: Linq to sql in c#

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

                            orderby s.average descending

                            select new XElement("student",

                                new XAttribute("name", s.name),

                                new XAttribute("average", s.average))

                                );

//Saving the document

xml.Save(@"c:\bestStudents.xml");

//Load xml document

XDocument loadedXml = XDocument.Load(@"c:\bestStudents.xml");

//Select only the best students

IEnumerable<student> best = from s in loadedXml.Elements("Students").Descendants()

                            where double.Parse(s.Attribute("average").Value) > 7

                            select new Student(name: s.Attribute("name").Value,

                                               average: double.Parse(s.Attribute("average").Value));

//Print the best students

foreach (var b in best)

    Console.WriteLine(b.name + " " + b.average);

    

output:

Bark 9

Luck 8

</student></student></student>

Page 36: Linq to sql in c#

35

36