2. Agenda
• Introduction
• ORM—Object-Relational Mapping
• Creating a LINQtoSQLTest Application
• Querying and Updating the Database
• Lazy Loading and Eager Loading
• Joining Two Tables
3. Introduction
• What is LINQ
• Language-Integrated Query (LINQ) is a set of extensions to the .NET
Framework that encompass language-integrated query, set, and
transform operations. It extends C# and Visual Basic with native
language syntax for queries and provides class libraries to take
advantage of these capabilities.
List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 100 };
• To find all the even numbers in this list, you might write code like this:
List<int> list1 = new List<int>();
foreach (var num in list) {
if (num % 2 == 0) list1.Add(num);
}
var list2 = from number in list where
number % 2 == 0 select
number;
4. Introduction
• What is LINQ
• Lambda expressions
• Lambda expression is actually a syntax change for anonymous methods. It is just
a new way of writing anonymous methods. Next, let's see what a lambda
expression is step by step.
• First, in C# 3.0, there is a new generic delegate type, Func<A,R>, which presents
a function taking an argument of type A, and returns a value of type R:
var veges3 = products.Get(
delegate (Product p) {
return p.ProductName.Contains("vegetable");
}
);
var veges4 = products.Get(p =>
p.ProductName.Contains("vegetable"));
5. ORM—Object-Relational Mapping
• LINQ to SQL is considered to be one of
Microsoft's new ORM products. So before
we start explaining LINQ to SQL, let us
first understand what ORM is.
• ORM stands for Object-Relational
Mapping. Sometimes it is called O/RM, or
O/R mapping. It is a programming
technique that contains a set of classes
that map relational database entities to
objects in a specific programming
language.
6. LINQ to SQL
• LINQ to SQL is a component of the .NET Framework
version 3.5 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 the
language-integrated queries in the object model into
SQL 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.
7. Creating a LINQtoSQL Test Application
Adding a LINQ to SQL Item to the Project
To start with, let’s add a new item to our project
TestLINQToSQLApp. The new item added
should be of type LINQ to SQL Classes, and
named Northwind, like in the Add New Item
dialog window shown below.
8. Creating a LINQtoSQL Test Application
After you click the button Add, the
following three files will be added to the
project: Northwind.dbml,
Northwind.dbml.layout, and
Northwind.designer.cs. The first file holds
the design interface for the database
model, while the second one is the XML
format of the model. Only one of them
can remain open inside the Visual Studio
IDE. The third one is the code-behind for
the model which defines the DataContext
of the model.
At this point, the Visual Studio LINQ to
SQL designer should be open and empty,
like the following diagram:
9. Connecting to the Northwind Database
• Open the Server Explorer window from the
left most side of the IDE.
• From Server Explorer, right click on Data
Connections and select Add Connection to
bring the add connection window.
10. Adding Tables and Views to the Design Surface
• Expand the connection until all the tables
are listed, and drag Products to the
Northwind.dbml design surface. You should
have a screen like in this diagram:
• Then drag the Categories table from Server
Explorer to the Northwind.dbml design
surface.
11. Adding Tables and Views to the Design Surface
• If you open the file Northwind.Designer.cs,
you will find following classes are generated
for the project:
public partial class NorthwindDataContext : System.Data.Linq.DataContext
public partial class Product : INotifyPropertyChanging, INotifyPropertyChanged
public partial class Category : INotifyPropertyChanging, INotifyPropertyChanged
public partial class Current_Product_List
12. Querying and Updating the Database
QUERYING RECORDS
NorthwindDataContext db = new NorthwindDataContext();
IEnumerable<Product> beverages = from p in db.Products
where p.Category.CategoryName == "Beverages"
orderby p.ProductName
select p;
UPDATING RECORDS
Product bev1 = beverages.ElementAtOrDefault(10);
if (bev1 != null) {
Console.WriteLine("The price of {0} is {1}. Update to 20.0", bev1.ProductName, bev1.UnitPrice);
bev1.UnitPrice = (decimal)20.00;
}
// submit the change to database
db.SubmitChanges();
13. Querying and Updating the Database
INSERTING RECORDS
NorthwindDataContext db = new NorthwindDataContext();
Product newProduct = new Product {ProductName="new test product" };
db.Products.InsertOnSubmit(newProduct);
db.SubmitChanges();
DELETING RECORDS
// delete a product
Product delProduct = (from p in db.Products
where p.ProductName == "new test product“
select p).FirstOrDefault();
if(delProduct != null)
db.Products.DeleteOnSubmit(delProduct);
db.SubmitChanges();
14. Lazy Loading and Eager Loading
Deferred (Lazy) Loading Versus Eager Loading
In one of the above examples, we retrieved the category name of a product by this expression:
p.Category.CategoryName == "Beverages"
Even though there is no such field called category name in the Products table, we can still get the
category name of a product because there is an association between the Products and Category table. On
the Northwind.dbml design surface, click on the line between the Products and Categories tables and you
will see all the properties of the association. Note, its participating properties are Category.CategoryID ->
Product.CategoryID, meaning category ID is the key field to link these two tables.
Because of this association, we can retrieve the category for each product, and on the other hand, we can
also retrieve the products for each category.
15. Lazy Loading and Eager Loading
Lazy Loading by Default
However, even with the association, the associated data is not loaded when the query is executed. For example, if we retrieve all
categories like this:
var categories = from c in db.Categories select c;
And later on we need to get the products for each category, the database has to be queried again.
This is because by default, lazy loading is set to true, meaning all associated data (children) are deferred loaded until needed.
16. Lazy Loading and Eager Loading
Eager Loading With Load Options
To change this behavior, we can use the LoadWith method to tell the DataContext to automatically load the
specified children in the initial query, like this:
using System.Data.Linq;
// eager loading products of categories
DataLoadOptions dlo2 = new DataLoadOptions();
dlo2.LoadWith<Category>(c => c.Products);
// create another data context, because we can't change LoadOptions of db
// once a query has been executed against it
NorthwindDataContext db2 = new NorthwindDataContext();
db2.Log = Console.Out;
db2.LoadOptions = dlo2;
var categories2 = from c in db2.Categories select c;
foreach (var category2 in categories2) {
Console.WriteLine("There are {0} products in category {1}", category2.Products.Count(),
category2.CategoryName);
}
db2.Dispose();
18. Lazy Loading and Eager Loading
Joining Two Tables
var categoryProducts = from c in db.Categories
join p in db.Products on c.CategoryID equals p.CategoryID into products
select new {c.CategoryName, productCount = products.Count()};
foreach (var cp in categoryProducts) {
Console.WriteLine("There are {0} products in category {1}", cp.CategoryName, cp.productCount);
}