part 1. an experience using linq to sql exploring the linq entity...

41
Cleveland State University CIS611 LINQ to SQL Lecture Notes Prof. V. Matos 1 Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity-Model What is LINQ ? 1[1] Language Integrated Query (or LINQ, pronounced “link”), is a set of Microsoft .NET technologies that provide built-in language querying functionality similar to SQL, not only for database access, but for accessing data from any source. The current LINQ family of technologies and concepts allows an extensible set of operators that work over objects, SQL data and XML data sources. It is expected that LINQ will expand in the future to a larger number of data domains. A gentle Introduction to LINQ [2] Let us consider the following C# code fragment using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConLinq1 { class Program { static void Main() { string[] myNames = { "Burke", "Connor", "Frank", "Bingo", "Bango", "Bongo", "Everett", "Albert", "George", "Becky", "Harris", "David" }; // make a list of names made of 5 characters var expr = from s in myNames where ((s.Length == 5) && (s.StartsWith("B"))) orderby s select s.ToUpper(); // show results foreach (string item in expr) Console.WriteLine(item); // show actual type of anonymous variable Console.WriteLine("expr type:\n" + expr.GetType()); Console.WriteLine("\nDone..."); Console.ReadLine(); } }//class } 1 [1] Taken from http://msdn.microsoft.com/en-us/library/bb386976.aspx [2] The LINQ Project .NET Language Integrated Query. Don Box and Anders Hejlsberg. Microsoft Corporation. May 2006. Available at http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/LINQ_Project_Overview.doc

Upload: others

Post on 14-Oct-2020

18 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

1

Part 1. An Experience Using LINQ to SQL

Exploring the LINQ Entity-Model

What is LINQ ? 1[1]

Language Integrated Query (or LINQ, pronounced “link”), is a set of Microsoft .NET technologies that provide built-in

language querying functionality similar to SQL, not only for database access, but for accessing data from any source.

The current LINQ family of technologies and concepts allows an extensible set of operators that work over objects,

SQL data and XML data sources. It is expected that LINQ will expand in the future to a larger number of data

domains.

A gentle Introduction to LINQ [2]

Let us consider the following C# code fragment

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConLinq1 { class Program { static void Main() { string[] myNames = { "Burke", "Connor", "Frank", "Bingo", "Bango", "Bongo", "Everett", "Albert", "George", "Becky", "Harris", "David" }; // make a list of names made of 5 characters var expr = from s in myNames where ((s.Length == 5) && (s.StartsWith("B"))) orderby s select s.ToUpper(); // show results foreach (string item in expr) Console.WriteLine(item); // show actual type of anonymous variable Console.WriteLine("expr type:\n" + expr.GetType()); Console.WriteLine("\nDone..."); Console.ReadLine(); } }//class }

1 [1] Taken from http://msdn.microsoft.com/en-us/library/bb386976.aspx [2] The LINQ Project .NET Language Integrated Query. Don Box and Anders Hejlsberg. Microsoft Corporation. May 2006. Available at http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/LINQ_Project_Overview.doc

Page 2: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

2

Output

BANGO BECKY BINGO BONGO BURKE expr type: System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.String,System.String] Done...

Here var expr defines an anonymous variable resulting from evaluating a LINQ query expression. A query expression

operates on one or more information sources by applying one or more query operators from either the standard set

of query operators or domain-specific operators. This expression uses three of the standard query operators: Where,

OrderBy, and Select. Observe the Where clause in this C# program is phrased using C# syntax (instead of mixing host

language and SQL syntax for instance).

The statements above are semantically identical to the following explicit syntax shown in C#:

var expr = myNames .Where ( (s => (s.Length == 5) && (s.StartsWith("B")) ) ) .OrderBy (s => s) .Select (s => s.ToUpper());

The arguments to the Where, OrderBy, and Select operators are called lambda expressions, which are fragments of

code much like delegates. They allow the standard query operators to be defined individually as methods and strung

together using dot notation.

Many query operators allow the user to provide a function that performs filtering, projection, or key extraction. The

query facilities build on the concept of lambda expressions, which provides developers with a convenient way to write

functions that can be passed as arguments for subsequent evaluation. Lambda expressions are similar to CLR

delegates and must adhere to a method signature defined by a delegate type. To illustrate this, we can expand the

statement above into an equivalent but more explicit form using the Func delegate type:

Func<string, bool> filter = s => (s.Length == 5) && (s.StartsWith("B")); Func<string, string> extract = s => s; Func<string, string> project = s => s.ToUpper(); var expr = names.Where(filter) .OrderBy(extract) .Select(project);

Anonymous types allow data types to encapsulate (on-the-fly) a set of properties (fields) into a single object without

having to first explicitly define a type. This is an important feature for the SQL-like LINQ feature that is integrated into

C# and VB.NET. Since anonymous types do not have a named typing, they must be stored in variables declared using

the var keyword, telling the C# compiler to use type inference for the variable. The properties created are read-only in

C#, however they are read-write in VB.net. In our example the type of the resulting expression is dynamically

determined after the query evaluates and results into

System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.String,System.String]

The output type is inferred as System.String.

Page 3: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

3

Another example is:

var person = new { FirstName = "John", LastName = "Smith", Salary = 75000.99 };

here the type of the variable person is the combination of two strings and a double, more specifically

<>f__AnonymousType0`3[System.String,System.String,System.Double]

LINQ Operators

LINQ to Objects2 extends any type that inherits from IEnumerable (which is almost every collection class in .NET, from

simple Arrays to List<T>) to support query operations similar to those available in SQL. We can write queries using

any of the built-in Standard Query Operators, or add our own operators if we need to. The standard operators cover a

wide variety of categories, at present there are over fifty that form the backbone of LINQ.

Operator Type Operator Name

Aggregation Aggregate, Average, Count, LongCount, Max, Min, Sum

Conversion Cast, OfType, ToArray, ToDictionary, ToList, ToLookup, ToSequence

Element DefaultIfEmpty, ElementAt, ElementAtOrDefault, First, FirstOrDefault,

Last, LastOrDefault, Single, SingleOrDefault

Equality EqualAll

Generation Empty, Range, Repeat

Grouping GroupBy

Joining GroupJoin, Join

Ordering OrderBy, ThenBy, OrderByDescending, ThenByDescending, Reverse

Partitioning Skip, SkipWhile, Take, TakeWhile

Quantifiers All, Any, Contains

Restriction Where

Selection Select, SelectMany

Set Concat, Distinct, Except, Intersect, Union

2 Retrieved 4/18/2010 http://msdn.microsoft.com/en-us/library/bb308959(v=MSDN.10).aspx

Page 4: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

4

What is LINQ to SQL?

LINQ to SQL is an (O/RM) Object Relational Mapping component of the .NET Framework that provides a run-time

infrastructure for managing relational data as objects. In LINQ to SQL, the data model of a relational database is

mapped to an object model expressed in the programming language of the developer. When the application runs,

LINQ to SQL translates into SQL the language-integrated queries in the object model and sends them to the database

for execution. When the database returns the results, LINQ to SQL translates them back to objects that you can work

with in your own programming language.

You can query the database using LINQ, as well as update/insert/delete data from it. LINQ to SQL fully supports

transactions, views, and stored procedures. It also provides an easy way to integrate data validation and business

logic rules into your data model.

Object-Design Surface

The Object Relational Designer (O/R Designer) provides a visual design surface for creating LINQ to SQL entity classes

and associations (relationships) that are based on objects in a database. In other words, the O/R Designer is used to

create an object model in an application that maps to objects in a database. It also generates a strongly-typed

DataContext that is used to send and receive data between the entity classes and the database. The O/R Designer

also provides functionality to map stored procedures and functions to DataContext methods for returning data and

populating entity classes. Finally, the O/R Designer provides the ability to design inheritance relationships between

entity classes.

Figure 3 shows a fragment of the COMPANY database rendered as a Class-Diagram. It includes three entity classes:

EMPLOYEE, WORKS_ON, and PROJEC. The attributes (also called properties or class variables) of each class map to the

columns of a corresponding table in the relational database. Each instance of a class entity represents a row within

the database table.

The arrows between the three entity classes represent associations/relationships between the different entities. These

are typically modeled using primary-key/foreign-key relationships in the database. The direction of the arrows on the

design-surface indicates whether the association is a one-to-one or one-to-many relationship. Strongly-typed

properties will be added to the entity classes based on this fact. For example, the Employee class has a one-to-many

relationship with the Works_On class, representing the fact an employee could have several assignments. This means

it will have a "WORK_ONs" property which is a collection of WORK_ON objects within that category. Appendix X

shows fragments of the WORKS_ON definition produced by the O/R Designer.

The right-hand method pane within the LINQ to SQL design surface (Figures 2 and 3) contains a list of stored

procedures that interact with our database model. For example methods such as “Hire_Employee”, “Add_Project”,

“Remove_Employee_From_Project” can be saved in the database to be invoked by our client applications.

Understanding the DataContext Class

Visual Studio persists .NET classes that represent the entities and database relationships that we have modeled. For

each LINQ to SQL designer file added to our solution, a custom DataContext class will also be generated. This

DataContext class is the main conduit by which we'll query entities from the database as well as apply changes. The

Page 5: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

5

DataContext class created will have properties that represent each Table we modeled within the database, as well as

methods for each Stored Procedure we added.

It tracks changes that you made to all retrieved entities and maintains an "identity cache" that guarantees that entities

retrieved more than one time are represented by using the same object instance. In general, a DataContext instance is

designed to last for one "unit of work" however your application defines that term.

The DataContext class contains the connection string information and the methods for connecting to a database and

manipulating the data in the database. By default, the DataContext class contains several methods that you can

call, such as the SubmitChanges method that sends updated data from LINQ to SQL classes to the database. You can

also create additional DataContext methods that map to stored procedures and functions. In other words, calling

these custom methods will run the stored procedure or function in the database that the DataContext method is

mapped to. You can add new methods to the DataContext class just as you would add methods to extend any class.

Page 6: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

6

Lab Experience

We assume you have installed a copy of the COMPANY database in your SQL-Server (for details about the datasets

consult Elmasri-Navathe textbook).

1. Create a new C# project. Call it Linq2Sql01

2. Open the Server Explorer and create a new Data Connection to the MS-SQL COMPANY database (see MS-SQL

Database Diagram in Appendix A).

3. You must add to the C# project a Linq class. Follow the steps:

(Main Menu) Project | Add New Item… | Linq to Sql class. Name it: CompanyLinq.dbml. Click OK

Figure 1. Adding a Linq to Sql class

Figure2. The Object/Relational Designer Surface

Page 7: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

7

4. Click on the Server Explorer. Open the Tables folder. Drag the EMPLOYEE, WORKS_ON, and PROJECT tables to the

Object-Relational Designer panel (see figure above). This diagram depicts the collection of entities and their defined

relationships (other components could be added later). Those elements are accessible from our application.

Figure 3. A Class-Diagram showing three entities (Employee, Works_On, Project) and their relationships.

5. Enter the following code:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Linq2Sql01 { class Program { static void Main(string[ ] args) { //demo1. Retrieve male employees CompanyLinqDataContext myContext = new CompanyLinqDataContext(); var query1 = from e in myContext.EMPLOYEEs where e.sex.Equals("M") select e; foreach (var e in query1) { Console.WriteLine("Name: {0} {1} \tDno: {2}", e.fname, e.lname, e.dno); } Console.WriteLine("\nDone..."); Console.ReadLine(); } } }

Page 8: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

8

Output

Observations

a) The new LINQ class was called CompanyLinq. Therefore its associated DataContext class is named:

CompanyLinqDataContext

b) The clause “var query1” defines query1 as a variable of “anonymous type”. The shape of query1 is dictated by

the result of the LINQ expression. In our example the type of query1 is similar to Employee type.

c) The LINQ expression consists of three parts: from … where … select …

d) In our example the “from” portion is: from e in myContext.EMPLOYEEs. The collection EMPLOYEEs is

provided by .NET as a way of traversing the EMPLOYEE table (its naming is done by .NET)

e) The filtering of data is done through the phrase: where e.sex.Equals(“M”). The condition is written in the

form expected by the host language (in this case C#). For instance, the previous expression could also be

written as where e.sex == „M‟. Notice that Intellisense provides a list of e attributes as soon as you type “e.”

f) The select clause defines the output. In this example the entire e data type is retrieved. You may use the

expression new (e. fname, e.Lname, e.dno) to create a new entity type holding the three attributes: first

name, last name, and dept. number.

Page 9: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

9

Organizing the Rest of the Tutorial.

Replace the main method entered before with the following (larger) sample. You can try each of the fragments by

uncommenting/commenting the corresponding demo (there are nine altogether).

using System; using System.Collections.Generic; using System.Linq; using System.Text; // trying LINQ on the company database namespace Linq2SqlCompany01 { class Program { static void Main(string[] args) { // STEP 1 // Open the Server Explorer. Add a New Connection to the // MS-SQL Database called: Company // --------------------------------------------------------------- // STEP 2. // You must add to the project a Linq class, do this // Main Menu Project | Add New Item | Linq to Sql class // name it: CompanyLinq.dbml. Click OK // ---------------------------------------------------------------- // STEP3 // Define a Linq Data-Contex object CompanyLinqDataContext myContext = new CompanyLinqDataContext(); try { // QUERY1: Listing all MALE employees //ShowMaleEmployees(myContext); // QUERY2: List all employees and projects in which they work //ShowEmployeesProjects1(myContext); //QUERY3. Similar to Query2 but using a 'JOIN' expression //ShowEmployeesProjects2(myContext); //DEMO4: Insert a new assignment for employee 123456789 //InsertSingleAssignment(myContext); //DEMO5: Insert multiple assignment for employee 123456789 //InsertMultipleAssignments(myContext); //DEMO6: Delete one assignment for 123456789 //DeleteSingleAssignment(myContext); //DEMO7: Delete multiple assignment for 123456789 (pno >= 10) //DeleteMultipleAssignments(myContext); //DEMO8: Using STORED PROC. Simple ResultSet made of one table type //CallStoredProcSimpleCase(myContext); //DEMO9: Using STORED PROC. Complex ResultSet made of various table type //CallStoredProcComplexCase(myContext); Console.WriteLine("\nDone..."); Console.ReadLine(); } catch (Exception e) { Console.WriteLine("\n Problems..." + e.Message); Console.ReadLine(); }

Page 10: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

10

}// main //-------------------------------------------------------------------------------------- public static void ShowMaleEmployees(CompanyLinqDataContext myContext) { var query1 = from e in myContext.EMPLOYEEs where e.sex == 'M' select e; foreach (EMPLOYEE emp in query1) { Console.WriteLine("{0} \t {1} {2}", emp.ssn, emp.fname, emp.lname); } }// ShowMaleEmployees // ---------------------------------------------------------------------- public static void ShowEmployeesProjects1(CompanyLinqDataContext myContext) { // for each employee list his/her projects // solution is based on (brute force) nested loops var query2e = from e in myContext.EMPLOYEEs select e; foreach (EMPLOYEE eRec in query2e) { Console.WriteLine("{0} {1}", eRec.ssn, eRec.lname); // find the assignments of the current employee var query2w = from w in myContext.WORKS_ONs where w.essn == eRec.ssn select w; foreach (WORKS_ON wRec in query2w) { // find the (single) project description of each assignment var query2p = (from p in myContext.PROJECTs where p.pnumber == wRec.pno select p).Single(); Console.WriteLine("\t{0} {1} {2}\t{3}", wRec.essn, wRec.pno, query2p.pname, wRec.hours); } } }// ShowEmployeesProjects1 // ---------------------------------------------------------------------- public static void ShowEmployeesProjects2(CompanyLinqDataContext myContext) { // for each employee list his/her projects // solution is based on (intelligent) join operations var query3 = from e in myContext.EMPLOYEEs from w in myContext.WORKS_ONs from p in myContext.PROJECTs where (e.ssn == w.essn) && (w.pno==p.pnumber) select new { e.ssn, e.lname, w.essn, w.pno, w.hours, p.pname }; foreach (var ewp in query3) { Console.WriteLine("{0} {1} Proj: {2} {3} Hours: {4} ", ewp.ssn, ewp.lname, ewp.pno, ewp.pname, ewp.hours); } }// ShowEmployeesProjects2 // ---------------------------------------------------------------------- public static void InsertSingleAssignment(CompanyLinqDataContext myContext) { // use Server Explorer. Create a Query to inspect assignments of 123456789 // (currently working on projects 1 and 2) // place 123456789 on project 3 for 1 hour WORKS_ON wRec = new WORKS_ON { essn = "123456789", pno = 3, hours = 1 }; myContext.WORKS_ONs.InsertOnSubmit(wRec); myContext.SubmitChanges();

Page 11: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

11

// use Server Explorer to inspect employee's work-load } // InsertSingleAssignment // ---------------------------------------------------------------------- public static void InsertMultipleAssignments(CompanyLinqDataContext myContext) { // use Server Explorer to see entries of 123456789 in WORKS_ON // create a list of assignments for emp 123456789 List<WORKS_ON> wList = new List<WORKS_ON>(); WORKS_ON w1 = new WORKS_ON(){ essn="123456789", pno=10, hours=1}; WORKS_ON w2 = new WORKS_ON(){ essn="123456789", pno=20, hours=1}; WORKS_ON w3 = new WORKS_ON(){ essn="123456789", pno=30, hours=1}; wList.Add(w1); wList.Add(w2); wList.Add(w3); myContext.WORKS_ONs.InsertAllOnSubmit(wList); myContext.SubmitChanges(); // use Server Explorer to see additions made to 123456789's workload }//InsertMultipleAssignments // ---------------------------------------------------------------------- public static void DeleteSingleAssignment(CompanyLinqDataContext myContext) { // use Server Explorer. Create a Query to inspect assignments of 123456789 // (currently working on projects 1, 2, 3, 10, 20, 30) // removing employee from project 3; var wRec = myContext.WORKS_ONs.Single( w => (w.essn == "123456789")&&(w.pno==3)); myContext.WORKS_ONs.DeleteOnSubmit(wRec); myContext.SubmitChanges(); } // ---------------------------------------------------------------------- public static void DeleteMultipleAssignments(CompanyLinqDataContext myContext) { // removing employee 123456789 from projects 10, 20, 30 // observe the use of DeleteAllOnSubmit to get rid of the list // (instead of DeleteOnSubmit used to eliminate a single instance) var assignments = (from w in myContext.WORKS_ONs where (w.pno >= 3) && ( w.essn =="123456789") select w); myContext.WORKS_ONs.DeleteAllOnSubmit(assignments); myContext.SubmitChanges(); }// DeleteMultipleAssignments // ---------------------------------------------------------- public static void CallStoredProcSimpleCase(CompanyLinqDataContext myContext) { // Calling a StoredProc that returns rows from a single table // use Server Explorer to write the following MSSQL proc. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * ** * * * * * * ALTER PROCEDURE dbo.GetProjectsByDept ( @theDeptNo int ) AS SET NOCOUNT ON select p.* from Project p where p.dnum = @theDeptNo; RETURN * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** */ // Open the Object-Relational Designer window // Drag the icon representing in the Server Explorer the // procedure. Drop it on the right-side panel (Methods) // Right-Click on the procedure to display a pop-up window // from which we choose PROPERTIES

Page 12: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

12

// On the property panel select RETURN TYPE and choose // PROJECT as the type to be made by the stored-proc // using anonymous type // var myProducts = myContext.GetProjectsByDept(5); // equivalent strongly-typed statement is IEnumerable<PROJECT> myProducts = myContext.GetProjectsByDept(5); foreach(var p in myProducts) { Console.WriteLine("{0} {1} {2}",p.pnumber, p.pname, p.dnum); } }//CallStoredProcSimpleCase // ---------------------------------------------------------- public static void CallStoredProcComplexCase(CompanyLinqDataContext myContext) { // Calling a StoredProc that returns rows from various tables // or returns a value made by a function (not a table type) // use Server Explorer to write the following MSSQL proc. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * ** * * * * * * ALTER PROCEDURE GetName2 (@aSSN int, @answer nvarchar(100) output ) as BEGIN -- Returns salutation + full-name of given employee DECLARE @gender nvarchar(2) set @answer = ' ' select @gender = sex from employee where ssn = @aSSN; if @@rowcount = 0 RETURN @answer; select @answer = (fname + ' ' + lname) from employee where ssn = @aSSN; if @gender = 'F' set @answer = 'Ms. ' + @answer else set @answer = 'Mr. ' + @answer; RETURN 0 END; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** */ // Open the Object-Relational Designer window // Drag the icon representing the proc from the Server // Explorer. Drop it on the right-side panel (Methods) // Calling a stored Function to get emp's full name String fullName = ""; var myResult = myContext.GetName2(123456789, ref fullName); Console.WriteLine("{0} ", fullName ); // Calling a stored proc returning rows from various tables // use Server Explorer to enter the folowing MSSQL procedure // test it. Drag to Object-Relational Designer right panel. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ALTER PROCEDURE dbo.GetEmpNameProjectName ( @theDno int ) AS select e.ssn, e.lname, p.pname, w.hours from employee e, project p, works_on w where e.ssn = w.essn and w.pno = p.pnumber and e.dno = @theDno; RETURN * * * * * * * * * * * *** * * * * * * * * * * * * * * * * * */ Console.WriteLine("\nEmployees in Dept 5"); var myMixedResults = myContext.GetEmpNameProjectName(5); foreach (var ep in myMixedResults) { Console.WriteLine("{0} {1} {2} {3}", ep.ssn, ep.lname, ep.pname, ep.hours);

Page 13: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

13

} }//CallStoredProcComplexCase }// program }

Page 14: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

14

Output

123456789 John Smith

222333444 Inigo Montoya

333445555 Franklin Wong

666884444 Ramesh Narayan

888665555 James Borg

987987987 Ahmad Jabbar

123456789 Smith

123456789 1 32.5 ProductX

123456789 2 7.5 ProductY

222333444 Montoya

333445555 Wong

333445555 1 1.0 ProductX

333445555 2 10.0 ProductY

333445555 10 10.0 Computerization

333445555 20 10.0 REORGANIZATION

453453453 English

453453453 1 20.0 ProductX

453453453 2 20.0 ProductY

666884444 Narayan

666884444 3 40.0 PRODUCTZ

888665555 Borg

888665555 20 0.0 REORGANIZATION

987654321 Wallace

987654321 20 15.0 REORGANIZATION

987654321 30 20.0 Newbenefits

987987987 Jabbar

987987987 10 35.0 Computerization

987987987 30 5.0 Newbenefits

999887777 Zelaya

999887777 10 10.0 Computerization

999887777 30 30.0 Newbenefits

123456789 Smith Proj: 1 ProductX Hours: 32.5

123456789 Smith Proj: 2 ProductY Hours: 7.5

333445555 Wong Proj: 1 ProductX Hours: 1.0

333445555 Wong Proj: 2 ProductY Hours: 10.0

453453453 English Proj: 1 ProductX Hours: 20.0

453453453 English Proj: 2 ProductY Hours: 20.0

666884444 Narayan Proj: 3 PRODUCTZ Hours: 40.0

Done...

Query1

Query2

Query3

Page 15: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

15

After INSERT operations (Using Server Explorer | New Query)

After DELETE records

Page 16: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

16

Using Stored-Procedures

Page 17: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

17

PART 2. Web Apps Using LINQ-to-SQL

Exploring the LinqDataSource Class

1. Create an ASP.NET Web Application (WebLinq2Sql1).

2. Right-click on the application. Add | New Item… | Linq to Sql Classes. Name it: COMPANY.dbml

3. Click on Server Explorer. Drag-drop on Object-Relational-Designer tables: EMPLOYEE, WORKS_ON,

PROJECT. Save the design.

4. Use Solution Explorer. Click on the DEFAULT.ASP (Design) page. Click on ToolBox > Data. Drag-Drop a

GridView on the ASP form.

5. Select the code-behind page of the Default.asp page. Modify the Page_Load method as follows:

protecetd void Page_Load(object sender, EventArgs e) { COMPANYDataContext myContext = new COMPANYDataContext(); var query1 = from emp in myContext.EMPLOYEEs where ((emp.sex == 'F') || (emp.dno == 5)) select emp; GridView1.DataSource = query1; GridView1.DataBind(); }

6. Execute the application. It will retrieve a list of employees who either are ladies or work for dept. no. 5.

Page 18: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

18

Version 2. A custom list of attributes – Using the new {…} clause

You may customize the output list produced by the LINQ expression and consequently adjust the GridView‟s

datasource. For instance, we may request the LINQ expression to project only the employee‟s SSN, first and last name,

and dept no. Similarly you may modify the aesthetics of this app by clicking on the gridView‟s menu button (top-

right) and selecting “Auto Format…”. Change to any of the predefined layouts, here we choose “Colorful”.

The previous example should be modified as follows:

protected void Page_Load(object sender, EventArgs e) { COMPANYDataContext myContext = new COMPANYDataContext(); var query1 = from emp in myContext.EMPLOYEEs where ((emp.sex == 'F') || (emp.dno == 5)) select new {emp.ssn, emp.fname, emp.lname, emp.sex, emp.dno}; GridView1.DataSource = query1; GridView1.DataBind(); }

Page 19: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

19

Web Demo 3. Adding a DropDown list & using its values to select data for the DataGrid.

Now we proceed to create a more complex web app. From a drop-down list the user will select a project and a

GridView will show all the employees affiliated to the selected project.

The key steps to the solution are as follows:

(a) Create a new web application call it WebLinq3. Add a “Linq to SQL class” to the application. Use the Server

Explorer to drag-drop the EMPLOYEE, WORKS_ON, and PROJECT tables to the Object-Designer Surface. Use

the Solution Explorer to show the Default.asp page. From the Toolbox drag-drop a Drop-Down list and a

GridView.

(b) Important! Change the AutoPostBack property of the drop-down list to true.

(c) the DataSource, and DataValueField attributes of the Drop-Down list will be a LINQ expression that retrieves

all the projects, and the project name (Pname) field respectively.

(d) The value DropDownList1.SelectedValue will be used in phrasing the LINQ expression producing Employees.

These changes will be detected with the .SelectedIndexChanged event of the drop-down list. The result of the

second LINQ query is the DataSource that feeds the GridView.

The final solution is

using System;

using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; namespace WebLinq3 { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // setting the drop-down list to show project names. Do it when the // page is loaded the first time (not as a result of a client's postbak) if (!Page.IsPostBack) { COMPANYDataContext myContext = new COMPANYDataContext(); var query1 = from pRec in myContext.PROJECTs select pRec; DropDownList1.DataSource = query1; DropDownList1.DataValueField = "Pname"; DropDownList1.DataBind(); } }

Page 20: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

20

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e) { COMPANYDataContext myContext = new COMPANYDataContext(); // retrieving employees working in selected project var query2 = from eRec in myContext.EMPLOYEEs from wRec in myContext.WORKS_ONs from pRec in myContext.PROJECTs where ((pRec.pname == DropDownList1.SelectedValue) && (pRec.pnumber == wRec.pno) && (wRec.essn == eRec.ssn)) select new { eRec.ssn, eRec.fname, eRec.lname, eRec.dno }; GridView1.DataSource = query2; GridView1.DataBind(); } } }

NOTE.

Must change the DropDown list

property AutoPostBack to true.

Page 21: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

21

Web Demo4. Complex Projection of Attributes from a Table.

In this new web-app we will list all projects and the total hours & employees working on them. Aggregation will be

used to compute sum and count values. We will „nicely‟ rename and format output columns. This is called „Shaping

Results‟.

1. Create a new web app call it: WebLinq2Sql4

2. Add | New items… | Linq to Sql classes | name it COMPANY.

3. Click on Server Explorer. Drag PROJECT, WORKS_ON, and EMPLOYEE tables to the Object-Relational

Designer.

4. Place a GridView control on the Default.asp page.

5. Add the following code-behind

protected void Page_Load(object sender, EventArgs e) { COMPANYDataContext myContext = new COMPANYDataContext(); var query1 = from w in myContext.WORKS_ONs from p in myContext.PROJECTs where (w.pno == p.pnumber) group w by new { w.pno, p.pname } into g select new { ProjID = g.Key.pno, Name = g.Key.pname, TotalHours = (decimal?)g.Sum(wr => wr.hours), TotalEmps = (int?)g.Count() }; GridView1.DataSource = query1; DataBind(); }

Note:

1. The expression (decimal?) is a cast on a nullable attribute (if null then empty).

2. .Key is an attribute produced by the GroupBy clause.

3. Observe multiple groupBy fields and selected fields made of aggregations.

Page 22: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

22

Web Demo5. Displaying n rows per page (Using a GridView and Skip( ) and Take( ) Methods

1. Create a new web project to show all records from the WORKS_ON table in a GridView.

2. Add a Hyperlink control to the asp page.

3. Enter the following code-behind.

using System; using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; namespace WebLinq2Sql2 { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // we add to the ASP Request.Path a variable (rowNumber) and // a value (3, 6, 9...). This pair is sent from the client to the server // each time the page visits the server int rowNumber = Convert.ToInt32( Request.QueryString["rowNumber"]); String nextNumber = (rowNumber + 3).ToString(); HyperLink1.NavigateUrl = Request.Path + "?rowNumber=" + nextNumber; MyPopulateGrid(rowNumber); } private void MyPopulateGrid(int rowNumber) { COMPANYDataContext myContext = new COMPANYDataContext(); // retrieve assignments var query1 = from w in myContext.WORKS_ONs orderby w.essn, w.pno select w; // notice the use of the Skip and Take methods GridView1.DataSource = query1.Skip(rowNumber).Take(3); DataBind(); } } }

Page 23: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

23

Web Demo 6. DeclarativeASP.NET Databinding Using a LinqDataSource

This app will display/update table data without coding. Setup is made via declarative statements affecting the GUI,

DataSource, and ASP elements. Data will be displayed in a GridView from where the user will be able to insert, delete,

and modify any Employee row.

1. Create a new ASP app.

2. Create a new Entity-Model: Add | New item…| Linq to Sql classes. Call new model: CompanyEntityModel.

3. Use Server Explorer. Drag-drop EMPLOYEE and DEPARTMENT tables.

4. Save all. Right-Click on the project‟s name to Build all the elements !!!

5. Place a GridView on the Default.asp (design view) page. Click on the top-right arrow-menu button to bring

the „GridView Tasks‟ dialog box.

6. Click the dropdown control Choose DataSource and select <New data source…>. Name it:

DepEmpLinqDataSource.

Page 24: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

24

7. CRITICAL. A sequence of Dialog boxes will appear. On the first one select the context object:

WebLinq2Sql6A.CompanyEntityModelDataModel. Click Next.

8. The next screen allows you to choose the table to feed the GridView. Select Employee. Check all the fields

(*). Click on the OrderBy button to sort by ssn. Click on Advanced button to add delete, insert, and update

capabilities. Click OK | Finish

9. Press the Finish button.

Page 25: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

25

10. Improve the aesthetics of the GridView. On the Default.asp page click on the arrow-menu (top-right). Click

on Auto Format, select one option (we picked up: “Autum”).

11. Other „beautification‟ feature is to apply a format to a field. Click on Edit Columns… choose salary, on the

property panel look for Data | DataFormatString. Enter the currency format {0:c}. Remove unwanted fields

from the Selected fields: box (we removed minitial, address, bdate).

12. Tap on the GridView Tasks menu button. Select the entries Enable Sorting, Enable Editing, and Enable

Deleting. Test the application and see progress so far.

13. Instead of displaying department number (dno) we want to show department name. Click on the arrow-

menu. Select Edit columns… On the Selected fields box tap the entry dno. Now click on the link Convert this

field into a TemplateField. The property panel for dno will appear. Change the property Appearance |

HeaderText to DeptName. Change the entries Behavior | SortExpression to Department.dname. Click OK.

Page 26: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

26

14. Now we must change the Default.asp source script. Locate the “DeptName” entry. Replace its

<ItemTemplate> clause with the following:

<ItemTemplate>

<asp:Label ID="Label1" runat="server"

Text='<%# Eval("Department.dname") %>'></asp:Label>

</ItemTemplate>

15. The form so far looks as follows:

16. Finally we want to change the DeptName TextBox for a DropDown control, such that when we hit Edit a list

of department name choices is seen. To that effect apply the following two steps. (a) First, use Toolbox|Data

to add a new LinqDataSource, associate it with the Department table; name it DepartmentLinqDataSource. (b)

Locate in the Source page of Default.asp the entry DeptName. Replace it with the following code:

Page 27: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

27

<EditItemTemplate>

<asp:DropDownList ID="DropDownList1"

DataSourceID="DepartmentLinqDataSource"

DataValueField="dnumber"

DataTextField="dname"

SelectedValue='<%#Bind("dno") %>'

runat="server"

/>

</EditItemTemplate>

17. We are ready. Run the application, work on the first row, click on the Edit link. You should see the following

image. Click on the dropdown box. Choose a new department name. Click on Update | Cancel.

Page 28: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

28

Web Demo7. Filtering a LinqDataSource

In this demo we will extend the previous application (Web Demo6). A dropdown box will provide a list of department

names. The user will click on one name and only employees affiliated to that department will be displayed.

1. Modify the GUI by adding a dropdown list as illustrated below (this control is called DropDownList2).

2. Click on the arrow-menu (top-right corner) of DropDownList2 to show the Tasks dialog box.

3. Click on the Configure Data Source…link.

4. The configuration wizard‟s box “Choose a Data Source” appears. (a) On the entry labeled: Select a DataSource

enter DepartmentLinqDataSource, (b) on the box Select a data field to display in the DropDownList select:

dname, (c) on the last box Select a data field value for the DropDownList select dnumber. Click OK.

5. Check the box Enable AutoPostBack of the DropDownList Tasks panel.

6. Now we must modify the GridView‟s datasource in such a way that the value in the DropDownList control determines

what employees should be displayed (dno restricted).

7. Click on the arrow-menu (top-right corner) of the DepEmpLinqDataSource control. On the LinqDataSource window

select Configure DataSource. The configuration wizard appears; click NEXT, to go to the second panel Configure Data

Selection.

Page 29: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

29

8. Click on the Where button. You will indicate on the next form that the Employee.dno value (displayed on the GridView

and supplied by the current data source) should be determined by the value selected in the control called

DropDownList2. See form below. Click Add button. Click Finish, respond No to next question.

9. We are ready to go. Test the application, you should see screens such as:

Page 30: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

30

Part 3. Advanced Features

Custom Validation - Enforcing Business Rules.

In this demo we will implement custom validation rules on top of the Entity-Model. When the graphical model .dbml

file is created two text files are visible on the IDE: a .dbmal.layout (xml) holding a layout specification of the model and

a .designer.cs file containing the C# definition of the entities.

The second file (designer.cs) includes a number of partial classes supporting detailed operations on the entities. Here

we could write our own version of what to do in the case of validation OnValidate(…), OnChanged, OnLoaded,

onCreated, etc.

Entity-Model Diagram A fragment of the Company.designer.cs file

#region Extensibility Method Definitions

partial void OnLoaded();

partial void OnValidate(System.Data.Linq.ChangeAction action);

partial void OnCreated();

partial void OnfnameChanging(string value);

partial void OnfnameChanged();

partial void OnminitChanging(System.Nullable<char> value);

partial void OnminitChanged();

partial void OnlnameChanging(string value);

partial void OnlnameChanged();

partial void OnssnChanging(string value);

partial void OnssnChanged();

...

partial void OnaddressChanging(string value);

partial void OnaddressChanged();

partial void OnsalaryChanging(System.Nullable<double> value);

partial void OnsalaryChanged();

In this example we want to enforce the following rule:

An employee’s salary should not be higher than her direct supervisor’s salary.

Steps:

1. Create a new console application (ConLinq2Sql7). Add a “LINQ to SQL class”, call it CompanyEmp. Set the

Entity-Model diagram, holding the Employee table.

2. Use the Server Explorer to isolate a pair of employees that we will use to test the app. In our case observe

employees Smith and Wong. Their salaries are 30K and 40K respectively. Notice that Mr. Wong supervises

Mr. Smith.

Page 31: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

31

3. Enter the following code in the Program.cs file

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConLinq2Sql7 { class Program { static void Main(string[ ] args) { // wanting to enforce rule: // employees can not make more than their supervisors CompanyEmpDataContext myContext = new CompanyEmpDataContext(); // obtain Mr. Smith's record he make $30K // (we know his supervisor Mr. Wong makes $40K.) var emp = (from e in myContext.EMPLOYEEs where e.lname.Equals("Smith") select e).Single(); try { // try this first to test the OnValidate method added to the // extension of the EMPLOYEE class. emp.salary = 50000; //should trow exception // try this later to test rule attached to OnbdateChange method // emp.bdate = DateTime.Now.AddDays(1); myContext.SubmitChanges(); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("Done..."); Console.ReadLine(); } } }

4. Execute the program. Use Server Explorer to inspect the EMPLOYEE table.

Page 32: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

32

Observe that Smith‟s salary was changed to 50K (this is higher than Wong‟s – which is in violation to the

company‟s rules- but at this point nothing prevents it from happening!).

5. Reset Smith‟s salary to 30K (use Server Explorer > Show Table Data > retype Salary 30000).

6. Now, to enforce the business rule indicated earlier we could either write a database trigger or locally put

code in the Entity-Model to perform custom validation. We will explore the second option.

7. Enhance the EMPLOYEE definition (originally placed in CompanyEmp.designer.dbml which is part of

CompanyEmp.dbml) by adding a new (partial) class to the project. The new fragment will include the

validation logic (in the onValidate hook). Enter the following code

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConLinq2Sql7 { // This fragment extends the EMPLOYEE class definition (originally placed // in CompanyEmp.designer.dbml which is part of CompanyEmp.dbml). // Here we add a validation method to attend the "update" operation public partial class EMPLOYEE { partial void OnValidate(System.Data.Linq.ChangeAction action) { CompanyEmpDataContext myContext = new CompanyEmpDataContext(); // you should add logic for the: insert & delete cases // here we just take care of update operations if (action == System.Data.Linq.ChangeAction.Update) { //find the supervisor's record var super = (from s in myContext.EMPLOYEEs where s.ssn == this.superssn select s).Single(); //is this employee making more than her supervisor? if (this.salary > super.salary) { String errorMsg = String.Format( "VIOLATION: {0} has salary > than supervisor {1}", this.lname, super.lname); throw new Exception(errorMsg); } } }//OnValidate // Observation: // changes to specific fields can be tested using the corresponding // OnFIELDChanged() method. For example OnbdateChange follows partial void OnbdateChanged() { if (this.bdate > DateTime.Now) { throw new Exception("Invalid Birthdate"); } }//OnbdateChanged }//EMPLOYEE }

8. Execute the program (make sure Smith‟s salary initially is $30K). You should see the output:

VIOLATION: Smith has salary > than supervisor Wong

Done...

Page 33: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

33

9. Modify Program.cs. Replace the line emp.salary = 50000; with emp.salary = 39000; this should not raise the

salary custom rule violation. Uncomment the birthdate assignment.

emp.salary = 39000; //should NOT trow exception

emp.bdate = DateTime.Now.AddDays(1); //to test birthdate change

10. The change in birth date raises an exception in the onbdateCanged( ) method.

Invalid Birthdate Done...

11. Neither field salary nor bdate is changed.

Page 34: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

34

Demo 2. Using Stored Procedures for Create, Retrieve, Update, Delete (CRUD) operations

The goal of this demo is to show how to replace the default LINQ CRUD operations for user-defined methods.

1. Create a new project: ConLinq2SqlPart4.

2. Use Server Explorer to enter three MS-SQL-SERVER stored procedures to insert, delete, and update

WORKS_ON records. The server-side T-SQL procedures are given below

myInsertWorksOn myDeleteWorksOn myUpdateWorksOn CREATE PROCEDURE dbo.myInsertWorksOn ( @essn char(9), @pno int, @hours decimal(5,1) ) /* inserting a new assignment into WORKS_ON table */ AS insert into WORKS_ON (essn, pno, hours) values ( @essn, @pno, @hours ) RETURN

CREATE PROCEDURE dbo.myDeleteWorksOn ( @essn char(9), @pno int ) /* deleting an assignment from the WORKS_ON table */ AS delete WORKS_ON where (essn = @essn) and (pno = @pno) RETURN

CREATE PROCEDURE dbo.myUpdateWorksOn ( @essn char(9), @pno int, @hours decimal(5,1) ) /* updating an assignment in the WORKS_ON table */ AS update WORKS_ON set hours = @hours where (essn = @essn) and (pno = @pno) RETURN

3. Create the Assignments Entity-Model by dropping the WORKS_ON table to the OR-designer. Drag to the

OR-Designer Methods Panel each of the server-side stored procedures

4. Click on the WORKS_ON entity and bring the property page. Look for the methods to insert, delete,

update. Individually change their default value “Use runtime” to each of the methods created above. For

instance when changing the delete method a Configure Behavior windows appears. Select the option

Customize, use the dropdown list to choose the stored procedure myDeleteWorksOn. Click on Apply.

Repeat the process for the insert and update operations. This will update the entity‟s property page (see

image below)

Page 35: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

35

Page 36: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

36

5. Ready to test. Enter the following code under Program.cs.

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Linq2SqlPart4 { class Program { static void Main(string[] args) { // tesing the custom-made UPDATE procedure using (ASSIGNMETSDataContext myContext = new ASSIGNMETSDataContext()) { var task = (from w in myContext.WORKS_ONs where (w.essn == "123456789") && (w.pno == 1) select w).Single(); Console.WriteLine("BEFORE hours {0}", task.hours); task.hours = 60; myContext.SubmitChanges(); } using (ASSIGNMETSDataContext myContext = new ASSIGNMETSDataContext()) { var task = (from w in myContext.WORKS_ONs where (w.essn == "123456789") && (w.pno == 1) select w).Single(); Console.WriteLine("AFTER hours {0}", task.hours); } // testing custom-made INSERT method using (ASSIGNMETSDataContext myContext = new ASSIGNMETSDataContext()) { try { // place 123456789 on project 3 for 1.8 hours WORKS_ON wRec = new WORKS_ON { essn = "123456789", pno = 3, hours = (decimal)1.8 }; myContext.WORKS_ONs.InsertOnSubmit(wRec); myContext.SubmitChanges(); Console.WriteLine("AFTER Inserting"); } catch (Exception ex) { Console.WriteLine("Problems inserting\n" + ex.Message); } }

Page 37: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

37

// testing custom-made DELETE method using (ASSIGNMETSDataContext myContext = new ASSIGNMETSDataContext()) { try { // remove 123456789 from project 3 var wRec = myContext.WORKS_ONs.Single( w => (w.essn == "123456789") && (w.pno == 3)); myContext.WORKS_ONs.DeleteOnSubmit(wRec); myContext.SubmitChanges(); Console.WriteLine("AFTER deleting"); } catch (Exception ex) { Console.WriteLine("Problems deleting\n" + ex.Message); } } Console.WriteLine("\nDone..."); Console.ReadLine(); } } }

6. Use Server Explorer to inspect results in the database

7. Done!

Page 38: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

38

Appendix A. MS-SQL SERVER - Company Database

Page 39: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

39

Appendix B. A Fragment of the DataContext definition for the WORKS_ON Entity.

[Table(Name="dbo.WORKS_ON")] public partial class WORKS_ON : INotifyPropertyChanging, INotifyPropertyChanged { private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); private string _essn; private int _pno; private System.Nullable<decimal> _hours; private EntityRef<EMPLOYEE> _EMPLOYEE; private EntityRef<PROJECT> _PROJECT; #region Extensibility Method Definitions partial void OnLoaded(); partial void OnValidate(System.Data.Linq.ChangeAction action); partial void OnCreated(); partial void OnessnChanging(string value); partial void OnessnChanged(); partial void OnpnoChanging(int value); partial void OnpnoChanged(); partial void OnhoursChanging(System.Nullable<decimal> value); partial void OnhoursChanged(); #endregion public WORKS_ON() { this._EMPLOYEE = default(EntityRef<EMPLOYEE>); this._PROJECT = default(EntityRef<PROJECT>); OnCreated(); } [Column(Storage="_essn", DbType="Char(9) NOT NULL", CanBeNull=false, IsPrimaryKey=true)] public string essn { get { return this._essn; } set { if ((this._essn != value)) { if (this._EMPLOYEE.HasLoadedOrAssignedValue) { throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); } this.OnessnChanging(value); this.SendPropertyChanging(); this._essn = value; this.SendPropertyChanged("essn"); this.OnessnChanged(); } } } [Column(Storage="_pno", DbType="Int NOT NULL", IsPrimaryKey=true)] public int pno { get { return this._pno; } set { if ((this._pno != value)) { if (this._PROJECT.HasLoadedOrAssignedValue) {

Page 40: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

40

throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); } this.OnpnoChanging(value); this.SendPropertyChanging(); this._pno = value; this.SendPropertyChanged("pno"); this.OnpnoChanged(); } } } [Column(Storage="_hours", DbType="Decimal(5,1)")] public System.Nullable<decimal> hours { get { return this._hours; } set { if ((this._hours != value)) { this.OnhoursChanging(value); this.SendPropertyChanging(); this._hours = value; this.SendPropertyChanged("hours"); this.OnhoursChanged(); } } } [Association(Name="EMPLOYEE_WORKS_ON", Storage="_EMPLOYEE", ThisKey="essn", IsForeignKey=true)] public EMPLOYEE EMPLOYEE { get { return this._EMPLOYEE.Entity; } set { EMPLOYEE previousValue = this._EMPLOYEE.Entity; if (((previousValue != value) || (this._EMPLOYEE.HasLoadedOrAssignedValue == false))) { this.SendPropertyChanging(); if ((previousValue != null)) { this._EMPLOYEE.Entity = null; previousValue.WORKS_ONs.Remove(this); } this._EMPLOYEE.Entity = value; if ((value != null)) { value.WORKS_ONs.Add(this); this._essn = value.ssn; } else { this._essn = default(string); } this.SendPropertyChanged("EMPLOYEE"); } } } [Association(Name="PROJECT_WORKS_ON", Storage="_PROJECT", ThisKey="pno", IsForeignKey=true)] public PROJECT PROJECT { get { return this._PROJECT.Entity; } set { PROJECT previousValue = this._PROJECT.Entity; if (((previousValue != value) || (this._PROJECT.HasLoadedOrAssignedValue == false))) {

Page 41: Part 1. An Experience Using LINQ to SQL Exploring the LINQ Entity …eecs.csuohio.edu/~sschung/cis612/LinqTutorial.pdf · 2014. 9. 2. · The current LINQ family of technologies and

Cleveland State University CIS611 – LINQ to SQL Lecture Notes – Prof. V. Matos

41

this.SendPropertyChanging(); if ((previousValue != null)) { this._PROJECT.Entity = null; previousValue.WORKS_ONs.Remove(this); } this._PROJECT.Entity = value; if ((value != null)) { value.WORKS_ONs.Add(this); this._pno = value.pnumber; } else { this._pno = default(int); } this.SendPropertyChanged("PROJECT"); } } } public event PropertyChangingEventHandler PropertyChanging; public event PropertyChangedEventHandler PropertyChanged; protected virtual void SendPropertyChanging() { if ((this.PropertyChanging != null)) { this.PropertyChanging(this, emptyChangingEventArgs); } } protected virtual void SendPropertyChanged(String propertyName) { if ((this.PropertyChanged != null)) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }