Tải bản đầy đủ (.pptx) (46 trang)

Chapter 6 - LINQ to SQL

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.71 MB, 46 trang )

© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
LINQ via C# 3.0
Chapter 6 – LINQ to SQL
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
LINQ to Relational Data

LINQ to DataSet

Leveraging the existing investment

LINQ to SQL

Designer-generated mapping

Custom mapping, ORM facilities

LINQ to Entities – VS2008 SP1

ADO.NET Data Services – VS2008 SP1
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
LINQ to DataSet

DataSets and DataTables do not
implement IEnumerable

You could roll your own

LINQ provides an AsEnumerable()
extension for DataSets in
System.Data.DataSetExtensions.dll
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel


LINQ to DataSet
DataSet dataSet = new DataSet("Library");
dataSet.ReadXml(libraryStream);
var books = dataSet.Tables[0].AsEnumerable();
var authors =
from book in books
select book.Field<string>("author");
Array.ForEach(authors.ToArray(),
Console.WriteLine);

LINQ to DataSet can be used as an object-based
LINQ to XML!
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
LINQ to SQL

The primary challenge:

Abstracting away the data source

DataSets are filled and queried in a non-
standard way

But LINQ to Objects != DB access

Retrieve 15 rows from a 1,000,000-row table

Retrieve items based on DB indexes

Support DB-paging, partitioning, views, sprocs, ...
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

IQueryable

LINQ to SQL isn’t based on IEnumerable

Instead, Table<T> implements IQueryable

Contains an Expression Tree

This expression tree is parsed by the query
provider at runtime
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Data Source Abstraction

We still use the same LINQ keywords and
query operators

The query provider translates them into something else
and executes them

SQL, Web Service calls, REST URLs, ...
from student in students
select new {
student.Name,
Average =
student.Grades.Average(
g => g.Value)
}
SELECT [t0].[Name], (
SELECT AVG([t1].[Value])
FROM [dbo].[Grades] AS [t1]

WHERE [t1].[StudentId] =
[t0].[Id]
) AS [Average]
FROM [dbo].[Students] AS [t0]
LINQ to SQL
Provider
students is
IQueryable<Student>
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Mapping Data to Objects

LINQ to Objects:

Data = objects

LINQ to SQL:

Data = normalized relational database tables

Objects = business entities, DAL, data contracts, ...

System.Data.Linq.Mapping.MappingSource

AttributeMappingSource

XmlMappingSource
LINQ to SQL is an
Object-Relational
Mapper
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

Attribute-Based Mapping
[Table(Name=“Courses”)]
public class Course
{
[Column(IsPrimaryKey=true]
public int Id {get;set;}
[Column(...)]
public string Name {get;set;}
}
[Table(Name=“Students”)]
public class Student
{
[Column(IsPrimaryKey=true]
public int Id {get;set;}
[Column(...)]
public string Name {get;set;}
}
[Table(Name=“Grades”)]
public class Grades
{
[Column(IsPrimaryKey=true]
public int Id {get;set;}
[Column(...)]
public int Value {get;set;}
[Association(...)]
public EntityRef<Student> Student ...
[Association(...)]
public EntityRef<Course> Course ...
}
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

The Data Context

The DataContext class is the LINQ to
SQL orchestrator
using (DataContext context =
new DataContext(@"D:\Temp\CourseManagement.mdf")) {
context.Log = Console.Out;
var product =
from student in context.GetTable<Student>()
from course in context.GetTable<Course>()
select new { Student=student, Course=course };
Table<Grade> grades = context.GetTable<Grade>();
int lastGradeId =
(from grade in grades
select (int?)grade.Id).Max() ?? 0;
Connection string,
mapping source
Obtain data
source
Table<T> is
IQueryable
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
DataContext Notes

DataContext is not just a portal to the
entities

It tracks changes and detects conflicts

It guarantees object identity


It is decoupled from the mapping source

It is lightweight: One per method scope
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
What’s Supported?

All language-integrated query operators

Most standard query operators

Inserts, updates and deletes

Custom SQL commands (strings)

Database creation from mapping

Transactional work

Preloading data (local queries)

Optimistic locking (concurrency control)
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Updating Data
using (DataContext context...) {
var toUpdate =
from student in context.GetTable<Student>()
where student.GetTable<Grade>()
.Average(g=> g.Value) < 90
select student;

foreach (Student student in toUpdate)
student.Grades.First().Value += 20;
context.SubmitChanges();
}
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Inserting Data
using (DataContext context...) {
Student alex = new Student { Id = 49, Name = "Alex" };
context.GetTable<Student>().InsertOnSubmit(alex);
//New student gets an automatic 100 in first two courses
int lastGradeId = context.GetTable<Grade>().Max(g => g.Id);
foreach (Course course in context.GetTable<Course>().Take(2))
context.Grades.InsertOnSubmit(new Grade {
Id = ++lastGradeId,
Course = course,
Student = alex,
Value = 100
});

context.SubmitChanges();
}
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Deleting Data
using (DataContext context...) {
foreach (Student student in
context.GetTable<Student>().Where(
s => s.Grades.Average(g => g.Value) < 80)) {
//Manual cascading delete
foreach (Grade grade in
context.GetTable<Grade>().Where(

g => g.StudentId == student.Id)) {
context.GetTable<Grade>().DeleteOnSubmit(grade);
}
context.GetTable<Student>().DeleteOnSubmit(student);
}
context.SubmitChanges();
}
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Conflict Management

Optimistic locking allows for conflict control
when examining and submitting changes
using (CourseManagementDataContext context...) {
ChangeSet changeSet = context.GetChangeSet();
//changeSet.Deletes, changeSet.Inserts, changeSet.Updates
try {
context.SubmitChanges(ConflictMode.ContinueOnConflict);
} catch (ChangeConflictException) {
foreach (var conflict in context.ChangeConflicts) {
conflict.Resolve(RefreshMode.KeepCurrentValues);
foreach (var memberConflict in conflict.MemberConflicts)
memberConflict.Resolve(newValue);
}
}
}
Expensive: Checks all members
Use a timestamp or a version field
[Column(IsVersion=true, …)]
Or avoid altogether
[Column(UpdateCheck=UpdateCheck.Never, …)]

© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Transactional Work

Just like ADO.NET, DataContexts
participate in transactions
using (TransactionScope scope = new TransactionScope())
using (DataContext context...) {
context.GetTable<Student>().InsertOnSubmit(new Student {
Id=12, Name="Josh"});
context.SubmitChanges();
//Without scope.Complete(), the changes are not committed
}
using (CourseManagementDataContext context...) {
Console.WriteLine("Student exists? " +
context.GetTable<Student>().Any(s => s.Name == "Josh"));
}
Ambient transaction
scope
© Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Explicit Transaction

Transactions can be performed explicitly

Not recommended if distributed transactions are
required
using (CourseManagementDataContext context...) {
context.Connection.Open();
context.Transaction =
context.Connection.BeginTransaction();
context.GetTable<Student>().InsertOnSubmit(new Student {

Id = 12, Name = "Josh“ });
context.SubmitChanges();
context.Transaction.Rollback();
}

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×