LINQ - DidaWiki
Download
Report
Transcript LINQ - DidaWiki
LINQ
Slides from Gang Luo, Xuting Zhao and
Damien Guard
What is LINQ?
Language Integrated Query
Make query a part of the language
Component of .NET Framework 3.5
Query without LINQ
Objects using loops and conditions
foreach (Customer c in customers)
if (c.Region == "UK") ...
Databases using SQL
SELECT * FROM Customers WHERE Region='UK'
XML using XPath/XQuery
//Customers/Customer[@Region='UK']
ADO without LINQ
SqlConnection con = new SqlConnection(...);
con.Open();
SqlCommand cmd = new SqlCommand(
@"SELECT * FROM Customers
WHERE c.Region = @Region", con
);
cmd.Parameters.AddWithValue("@Region", "UK");
DataReader dr = cmd.ExecuteReader();
while (dr.Read()) {
string name = dr.GetString(dr.GetOrdinal("Name"));
string phone = dr.GetString(dr.GetOrdinal("Phone"));
DateTime date = dr.GetDateTime(3);
}
dr.Close();
con.Close();
Query with LINQ
C#
var myCustomers = from c in customers
where c.Region == "UK"
select c;
More LINQ queries
var goodCusts = (from c in db.Customers
where c.PostCode.StartsWith("GY")
orderby c.Sales descending
select c).Skip(10).Take(10);
Local variable type inference
Compiler can infer types from initializer
assignments
var keyword indicates compiler inferred type
Still strong-typed
This is not like JavaScript var
var a = 10; // Simple types
var x = new {
Blog = “attardi”, Created = DateTime.Now };
// Anonymous types
Essential when using anonymous types
Anonymous Types
Object of new type generated on the fly without first defining
it.
Useful for projection to select one or more fields of another
structure.
The type will be dynamically generated with setters and
getters to corresponding members.
Some common methods are also provided.
No other methods will be added to this type.
But that is already enough!
The object is created and initialized by Anonymous Object
Initializer.
Advantages
Unified data access
Single syntax to learn and remember
Strongly typed
Catch errors during compilation
IntelliSense
Prompt for syntax and attributes
Bindable result sets
Architecture
LINQ to Objects
int[] nums = new int[] {0,4,2,6,3,8,3,1};
double average = nums.Take(6).Average();
var above = from n in nums
where n > average
select n;
LINQ to Objects
Query any IEnumerable<T> source
Includes arrays, List<T>, Dictionary...
Many useful operators available
Sum, Max, Min, Distinct, Intersect, Union
Expose your own data with
IEnumerable<T> or IQueryable<T>
Create operators using extension methods
LINQ operators
Aggregate Conversion
Aggregate
Average
Count
Max
Min
Sum
Ordering Partitioning
Cast
OrderBy
OfType
ThenBy
ToArray
Descending
ToDictionary Reverse
ToList
ToLookup
ToSequence
and others …
Skip
SkipWhile
Take
TakeWhile
Sets
Concat
Distinct
Except
Intersect
Union
Query Expression
SQL-like:
from s in names
where s.Length == 5 orderby select s.ToUpper();
OO-style:
names.Where(s => s.Length==5)
.OrderBy(s => s)
.Select(s => s.ToUpper());
Where, OrderBy, and Select are operators.
The arguments to these operators are
Lambda Expression.
Lambda Expressions
Examples:
s => s.Length == 5
Executable function
Anonymous functional. Can be assigned to a delegate
variable.
No need to indicate the types
Can be passed to methods as parameters.
Expression Tree
Efficient in-memory data representations of lambda
expressions
Changing the behaviors of the expressions
Applying your own optimization
Function Types
Func<int, bool> is a shorthand for
public delegate bool Func(int a0);
// Initialized with anonymous method
Func<int, bool> even=
delegate (int x) { return x % 2 == 0; };
// Initialized with lambda expression
Func<int, bool> even2 = x => x % 2 == 0;
Methods Extension
Control not only by Lambda Expression, but
also by methods extension
public static class Enumerable {
public static IEnumerable<T> Where<T>(
this IEnumerable<T> source,
Func<T, bool> predicate) {
foreach (T item in source)
if (predicate(item))
yield return item;
}
}
LINQ Operations
Join
When there is relationship (e.g. foreign key) between two tables,
no explicit join operation is needed
Using dot notation to access the relationship properties, and
navigate all the matching objects.
var q = from o in db.Orders where o.Customer.City == “London”
select o;
To join any two data sources on any attribute, you need an
explicit join operation.
var query = names.Join(people, n => n, p => p.Name, (n, p) =>
p);
The lambda expression for shaping (n, p) => p will be applied on
each matching pairs.
LINQ Operations (cont.)
Group Join
The lambda expression for shaping is applied on the
outer element and the set of all the inner elements that
matches the outer one.
Shape the result at a set level
var query = names.GroupJoin(people,
n => n,
p => p.Name,
(n, matching) => new { Name = n, Count =
matching.Count() }
)
LINQ Operations (cont.)
Select Many
Each object in the result set may contain a collection or array
Select many help decompose the structure and flatten the result
var query = names.SelectMany(n =>
people.Where(p => n == p.Name))
All the elements could be traversed in one foreach loop.
Aggregation
Standard aggregation operators: Min, Max, Sum, Average.
int totalLength=names.Sum(s => s.Length);
General purpose (generic) operator:
static U Aggregate<T, U>(this IEnumerable<T> source,
U seed, Func<U, T, U> func)
LINQ Deferred
A LINQ data source can actually implement
one of two interfaces:
IEnumerable<T>
IQueryable<T>
public interface IQueryable<T> :
IEnumerable<T>, IQueryable, IEnumerable {
IQueryable<S> CreateQuery<S>(Expression
exp);
S Execute<S>(Expression exp);
}
Create deferred query execution plan
IQueryable
IQueryable<T> interface will defer the
evaluation of the query.
An expression tree will represent all the
deferred queries as a whole.
Several operations could be “merged”, only
one SQL query will be generated and sent to
database.
Multi-level defer
Lambda Expressions Revisited
Lambda expressionscan represent either IL
code or data
Expression<T> makes the difference
Func<int, bool> lambdaIL =
n => n % 2 == 0;
Expression<Func<int, bool>> lambdaTree =
n => n % 2 == 0;
Compiler handles Expression<T> types
differently
Emits code to generate expression tree instead of
usual IL for delegate
Expression Trees
Expression tree are hierarchical trees of
instructions that compose an expression
Add value of expression trees
Actual creating of IL is deferred until execution of
query
Implementation of IL creation can vary
Trees can even be remoted for parallel
processing
Creating IL from Expression Trees
Right before execution tree is compiled into IL
Expression<Func<Posting,bool>> predicate =
p => p.Posted < DateTime.Now.AddDays(-5);
Func<Posting,bool> d = predicate.Compile();
Implementation of IL generation differs very
much for each Linq flavor.
Linq to SQL generates IL that runs SQL
commands
Linq to Objects builds IL with Sequence
extensions methods
Nested defer
Nested defer
var q = from c in db.Customers
where c.City == “London”
select new { c.ContactName, c.Phone }
var q2 = from c in q.AsEnumerable()
select new {
Name = DoNameProcessing(c.ContactName),
Phone = DoPhoneProcessing(C.Phone)
};
What if you want the intermediate result?
string lastName = “Simpson”
var persons = from p in personList where p.LastName = lastName select p;
lastName = “Flanders”
foreach (Person p in persons)
Console.WriteLine(“{0} {1}”, p.FirstName, p.LastName);
Deferred Execution
Advantages
Performance!
Query dependency!
Disadvantages
Divide one query into multiple ones
If you iterate over the result set 100
times, the query will be executed 100
times.
Users have to be very careful
LINQ to SQL
Data Model
[Table(Name=“Customers”)]
public class Customer {
[Column(Id=true)]
public string CustomerID;
…
private EntitySet<Order> _Orders;
[Association(Storage=“_Orders”, OtherKey=“CustomerID”)]
public EntitySet<Order> Orders {
get { return _Orders; }
set { _Orders.Assign(value); }
}
}
LINQ to SQL helps connect to relational and manipulate the
relational data as objects in memory.
It achieves this by translating the operations into SQL statements.
LINQ to SQL
Object-relational mapping
Records become strongly-typed objects
Data context is the controller mechanism
Facilitates update, delete & insert
Translates LINQ queries behind the scenes
Type, parameter and injection safe
Database mapping
Map tables & fields to classes & properties
Generates partial classes with attributes
Each record becomes an object
Data context represents the database
Utilize tables, views or stored procedures
Modifying objects
Update
Set object properties
Delete
context.Table.DeleteOnSubmit(object)
Insert
context.Table.InsertOnSubmit(object)
Commit changes back
context.SubmitChanges()
Transactional - all or nothing
Consistency
Every object will be tracked by LINQ the
moment it is loaded from database.
The tracking mechanism monitor the
manipulation on relationship properties.
Once you modify one side of the relationship,
LINQ will modify the other to keep it
consistent.
When an object is deleted, it could still exist in
memory, but it will not cause inconsistency.
Concurrency
Optimistic concurrency
Conflict checking when SubmitChanges() is
called
By default, transaction will abort and an
exception will be thrown when a conflict is
detected.
User can handle the conflict in the exception
catch block.
User can set whether or not to detect the
conflict when one column get updated.
Transaction/Update
When update, first check whether new object
is added (by tracking mechanism) if yes,
insert statement will be generated.
What does Django do here?
Modification will not hit the database until the
SubmitChanges() method is called
All operations will be translated into SQL
statements
All modifications will be encapsulated into a
transaction.
Transaction/Update (cont.)
If an exception is throw during the
update, all the changes will be rolled
back
One SubmitChanges() is actually one
transaction. (pros and cons?)
Users can also explicitly indicate a new
transaction scope.
LINQ to XML Class Hierarchy
http://msdn.microsoft.com/en-us/library/bb308960.aspx
LINQ to XML
LINQ to XML
var query = from p in people
where p.CanCode
select new XElement(“Person”,
new XAttribute(“Age”, p.Age),
p.Name);
XML to LINQ
var x = new XElement(“People”,
from p in people
where p.CanCode
select
new XElement(“Person”,
new XAttribute(“Age”, p.Age),
p.Name);
Performance
LINQ has more control and efficiency in O/R
Mapping than NHibernate
LINQ: Externl Mapping or Attribute Mapping
NHibernate: Externl Mapping
Because of mapping, LINQ is slower than
database tools such as SqlDataReader or
SqlDataAdapter
In large dataset, their performance are more and
more similar