sarang s. datye microsoft global services india enhancing developer productivity - the linq way
TRANSCRIPT
Sarang S. DatyeMicrosoft Global Services India
Enhancing Developer Productivity - The LINQ way.
Agenda
Introduction
• Comparing ADO.NET with LINQ
DataContext
• Understanding DataContext against IDbConnection
Attribute Mapping
• Mapping .NET Objects to SQL Object
CodeGen tools
• VS Designer, SQLMetal
DML thru LINQ to SQL
• Using LINQ to perform Insert, Update, Delete
Using Stored Procedures
• Calling Stored Procedures to bind with .NET Objects
LINQ Transactions
• Enlisting LINQ queries in transactions
Introduction
LINQ = Language INtegrated QueriesQuery Expression, Lambdas, Extension methods…
LINQ to SQL = Managing Relations data as objects using LINQ
LINQ to SQLAccessing data today
SqlConnection c = new SqlConnection(…);c.Open();SqlCommand cmd = new SqlCommand( @"SELECT c.Name, c.Phone FROM Customers c WHERE c.City = @p0");cmd.Parameters.AddWithValue("@p0", "London“);DataReader dr = c.Execute(cmd);while (dr.Read()) { string name = dr.GetString(0); string phone = dr.GetString(1); DateTime date = dr.GetDateTime(2);}dr.Close();
Queries in quotes
Loosely bound arguments
Loosely typed result sets
No compile time checks
public class Customer { … }
public class Northwind : DataContext{ public Table<Customer> Customers; …}
Northwind db = new Northwind(…);var contacts = from c in db.Customers where c.City == "London" select new { c.Name, c.Phone };
LINQ to SQLAccessing data with LINQ
Classes describe data
Strongly typed connections
Integrated query syntax
Strongly typed results
Tables are like collections
LINQ to SQL
Language integrated data accessMaps tables and rows to classes and objectsBuilds on ADO.NET and .NET Transactions
MappingEncoded in attributes or external XML fileRelationships map to properties
PersistenceAutomatic change trackingUpdates through SQL or stored procedures
DataContext• A DataContext is used to scope changes made to classes defined by LINQ to SQL
• A DataContext is responsible for keeping references to all LINQ to SQL classes, their properties, and foreign key relationships.
• A DataContext is not meant to be kept around; we want to create a new context for every “unit of work” to avoid concurrency issues. There are multiple ways to approach this.
• A DataContext is the API to the database, but at this stage it does not contain any business logic that is not implied by the database schema.
Defining DataContext
Inherit from DataContextOverride Constructor(s)
[Database(Name = “MyDB")]public class MyDataContext : DataContext{ public MyDataContext(string connString)
: base(connString) { }}
Creating DataContext
Similar to SqlConnection()
public static void Main(){ string connString = “server=MyServer; database=MyDb”; MyDataContext context = new MyDataContext(connString); : : :}
DataContext Demo
LINQ Queries
SQL “like” SyntaxNot a hack/kludgeBuilt upon
GenericsExtension methodsLamdas
var result = from cust in context.Customers where cust.Location = “Pune” select cust;
foreach (Customer c in result){ Console.WriteLine(c.CustomerName);}
LINQ Queries
LINQ To SQL fetches data from databasePopulates the Table Object/EntitySetBasic LINQ semantics allows iteration
join Query
SQL “Like” joinInner join implemented as natural syntaxOuter joins thru “DataShapes”
var result = from c in Customers join o in Order on c.CustomerID equals o.CustomerID select new { c.CustomerName, o.OrderID }
foreach (var v in result){ Console.WriteLine(v);}
JOIN DEMO
Inner JoinsSELECT [t1].[ASListID], [t1].[QID] FROM [Question] AS [t0] INNER JOIN [QuestionSelection] AS [t1] ON [t0].[QID] = [t1].[QID] WHERE EXISTS( SELECT t3.ASListID FROM [AnswerStep] AS [t2] INNER JOIN [AnswerStepSelection] AS [t3] ON [t2].[ASID] = [t3].[ASID] INNER JOIN [AnswerStepList] AS [t4] ON [t3].[ASListID] = [t4].[ASListID] WHERE ([t3].[ASListID] = [t1].[ASListID]) AND ([t4].[QuestionAreaID] = 1) )
(from t in context.GetTable<ConsoleApplication3.TailoringQuestion>()join t1 in context.GetTable<ConsoleApplication3.TailoringQuestionSelection>()on t.TQID equals t1.TQIDselect new { t1.PSListID, t1.TQID }).Where(n => (from p in context.GetTable<ConsoleApplication3.ProgramStep>() join p1 in context.GetTable<ConsoleApplication3.ProgramStepSelection>() on p.PSID equals p1.PSID join p2 in context.GetTable<ConsoleApplication3.ProgramStepList>() on p1.PSListID equals p2.PSListID where ((p2.AuditAreaID == 1)) select p1.PSListID).Contains(n.PSListID));
Attribute Mapping
Declarative mappingNo code requiredMap Relational to Objects
[Table(Name=“prod”)]public class Product{ [Column(Name=“ProdId”, IsPrimaryKey=true)] public string ProductID;
[Column] public string ProductName;}
Attribute Mapping Demo
XML Mapping
Externalized mappingCan be modified without rebuildCan be generated dynamically
Sample xml mapping file
<?xml version="1.0" encoding="utf-8"?><Database Name="northwind" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007"> <Table Name="dbo.Customers" Member="Customers"> <Type Name="Customer"> <Column Name="CustomerID" Member="CustomerID" Storage="_CustomerID" DbType="NChar(5) NOT NULL" CanBeNull="false" IsPrimaryKey="true" /> <Column Name="CompanyName" Member="CompanyName" Storage="_CompanyName" DbType="NVarChar(40) NOT NULL" CanBeNull="false" /> </Type> </Table></Database>
XML Mapping Demo
Code Generation Tools
Attribute and XML can be manually generatedCodeGen Tools
VS Designer ToolLink to SQL class itemServer Explorer Drag and Drop
SQLMetal.exeCan generate DBML (Database Markup Language)XML Mapping FileAttribute mapped code file (.cs|.vb)
VLinq Visual design LINQ Querieshttp://code.msdn.microsoft.com/vlinq
SQLMetal Demo
LINQ Associations
Mirror database relation in object collectionMaster-Detail mappingData available thru Object Collections
[Table(Name=“Customers”]Class Customer{ [Column] public string CustomerID; [Column]public string CompanyName;
[Association(ThisKey=“CustomerID”, OtherKey=“CustomerID”] public EntitySet<Order> orders;}
[Table(Name=“Orders”)]public class Order{ [Column] public string CustomerID; [Column] public stringOrderID;}
Association Thru XMLMapping
Similar to attribute
<?xml version="1.0" encoding="utf-8"?><Database Name="northwind" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007"> <Table Name="dbo.Customers" Member="Customers"> <Type Name="Customers"> <Column Name="CustomerID" Member="CustomerID" Storage="_CustomerID" DbType="NChar(5) NOT NULL" CanBeNull="false" IsPrimaryKey="true" /> <Column Name="CompanyName" Member="CompanyName" Storage="_CompanyName" DbType="NVarChar(40) NOT NULL" CanBeNull="false" /> <Association Name="FK_Orders_Customers" Member="Orders" Storage="_Orders" ThisKey="CustomerID" OtherKey="CustomerID"/> </Type> </Table> <Table Name="dbo.Orders" Member="Orders"> <Type Name="Orders"> <Column Name="OrderID" Member="OrderID" Storage="_OrderID" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> <Column Name="CustomerID" Member="CustomerID" Storage="_CustomerID" DbType="NChar(5)" /> <Column Name="OrderDate" Member="OrderDate" Storage="_OrderDate" DbType="DateTime" /> </Type> </Table></Database>
Association Demo
Call StoreProcedures
SPs can be mapped thru attributes or XMLCall semantics similar to tablesSupports parameter passing (in/out)Existing Entity behaviour can be changed to use SPs instead of SQL
LINQ to Entitiesusing(AdventureWorksDB aw = new AdventureWorksDB(Settings.Default.AdventureWorks)) { Query<SalesPerson> newSalesPeople = aw.GetQuery<SalesPerson>( "SELECT VALUE sp " + "FROM AdventureWorks.AdventureWorksDB.SalesPeople AS sp " + "WHERE sp.HireDate > @date", new QueryParameter("@date", hireDate));
foreach(SalesPerson p in newSalesPeople) { Console.WriteLine("{0}\t{1}", p.FirstName, p.LastName); }}
using(AdventureWorksDB aw = new AdventureWorksDB(Settings.Default.AdventureWorks)) { var newSalesPeople = from p in aw.SalesPeople where p.HireDate > hireDate select p;
foreach(SalesPerson p in newSalesPeople) { Console.WriteLine("{0}\t{1}", p.FirstName, p.LastName); }}
LINQ to Entities..contd.
LINQ to SQL ADO.NET Entities Framework
Database Support
SQL Server Many
Object Relational Mapping Capabilities
Simple -> 1:1 Complex
Metadata Attributes edmx file
LINQ to DataSets
Accessing from the DataSet
DataSet ds = new DataSet();FillOrders(ds); // this method fills the DataSet from a database
DataTable orders = ds.Tables["SalesOrderHeader"];
var query = from o in orders.ToQueryable() where o.Field<bool>("OnlineOrderFlag") == true select new { SalesOrderID = o.Field<int>("SalesOrderID"), OrderDate = o.Field<DateTime>("OrderDate") };
foreach(var order in query) { Console.WriteLine("{0}\t{1:d}", order.SalesOrderID, order.OrderDate);}
Accessing from the DataSet with JoinsDataSet ds = new DataSet();FillOrders(ds);
DataTable orders = ds.Tables["SalesOrderHeader"];DataTable details = ds.Tables["SalesOrderDetail"];
var query = from o in orders.ToQueryable() join d in details.ToQueryable() on o.Field<int>("SalesOrderID") equals d.Field<int>("SalesOrderID") where o.Field<bool>("OnlineOrderFlag") == true select new { SalesOrderID = o.Field<int>("SalesOrderID"), OrderDate = o.Field<DateTime>("OrderDate"), ProductID = d.Field<int>("ProductID"), Quantity = d.Field<short>("OrderQty") };
foreach(var line in query) { Console.WriteLine("{0}\t{1:d}\t{2}\t{3}", line.SalesOrderID, line.OrderDate, line.ProductID, line.Quantity);}
Feedback / QnA
Your Feedback is Important!Please take a few moments to fill out our
online feedback form at: << Feedback URL – Ask your organizer for this in advance>>
For detailed feedback, use the form at http://www.connectwithlife.co.in/vtd/helpdesk.aspx
Or email us at [email protected]
Use the Question Manager on LiveMeeting to ask your questions now!
© 2007 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.
The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after
the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.