360 likes | 484 Vues
This blog delves into LINQ (Language Integrated Query) as a powerful tool within enterprise applications. Learn about its foundational role in Microsoft’s Object-Relational Mapping (ORM) solutions and how it simplifies creating, retrieving, updating, and deleting data. Explore essential concepts like implicit typing, lambda expressions, and query execution. We will strategically highlight the importance of understanding over mere completion and encourage questions along the way. Dive into demos, practical applications, and the innovative features that LINQ offers for modern development workflows.
E N D
Diane WilsonMCSD .NET diane@firelily.com dwilson@centice.com Blog: http://toomanylayers.blogspot.com/ LINQ for Enterprise Applications
Rules of Engagement • Information overload • Focus on enterprise design issues • Ask questions at any time • Understanding is more important than completion • We’ll try for completion, also
LINQ Defined • LINQ = Language INtegrated Query • C# and VB.NET • General purpose query capability • Object collections (including DataSets) • XML • SQL Server • Create, Retrieve, Update, Delete (CRUD) • Foundation for Microsoft’s ORM solution • Entity to database relationships • Change tracking
Overview • Demo • Deconstructing LINQ • Object-Relational Mapping (ORM) • Putting LINQ to Work
Overview • What Won’t Get Discussed • Not a tutorial • LINQ to XML • Many LINQ Query Operators • 52 standard query operators (plus overloads) would take all night! • Not to mention dozens of provider-specific query operators…
Demo • See LINQ! See LINQ Run! • PainfulSample.aspx.cs • SimpleSample.aspx.cs
Deconstructing LINQ • Example: Syntax.aspx.cs • Implicit typing, anonymous types, object initialization • LINQ syntax • Lambda expressions • Fun facts about LINQ queries • Other language enhancements • DataContext class • Viewing and debugging the query
Deconstructing LINQ • Implicit typing, anonymous types, object initialization (C#) • varmyCat = new {name=“Storm”, breed=“Abyssinian”, color=“fawn”, age=3}; • “var” defines an implicitly typed variable, based on initialization • Usage limited to local variables only • myCat contains an anonymous object • Compiler-generated class name • Members defined by initialization • Object initialization at create time • Names, types, and values • No Constructor
Deconstructing LINQ • Implicit typing, anonymous types, object initialization • C# Syntax • varmyCat = new {name=“Storm”, breed=“Abyssinian”, color=“fawn”, age=3}; • VB Syntax • Dim myCat = new with {.name=“Storm”, _ .breed=“Abyssinian”, .color=“fawn”, .age=3}
Deconstructing LINQ • LINQ Syntax • Query format • var cats = from cat in Categories where cat.ID == 3 select cat; • Method format • Category myCat = cats.Where(c => c.ID == 3).Select(s => s).SingleOrDefault(); • Mixed format • Category myCat = (from cat in Categories where cat.ID == 3 select cat).SingleOrDefault();
Deconstructing LINQ • LINQ Query Structure • varmyQuery = from cat in NW.Categories select cat; • “NW” is a DataContext providing access to Northwind • “from cat in NW.Categories” defines “cat” as an iterator over NW.Categories • “cat” is of type NW.Category • Scope of “cat” is the LINQ statement • “select cat” returns NW.Categoryobjects • “myQuery” is implicitly typed • Query returns type IQueryable<T> or IEnumerable<T> • “T” based on “select”, not on iterator or data source
Deconstructing LINQ • Lambda expressions • Compact syntax for anonymous methods • Functional notation • C# syntax: ((x, y) => x == y) • VB syntax: (function(x, y) x = y) • Used as delegates • .Where (c => c.ID == cat.CategoryID) • “.Where” is an extension method on IEnumerable<T> • “.Where” defined with “Func” generic delegate • Lambda expression can have a block of statements with return value
Deconstructing LINQ • Fun Facts about LINQ Queries • “from cat in Categories select cat” • Defines a query • Query does not execute until needed • Queries are of type IEnumerable<T> or IQueryable<T> • Where <T> is the class being selected • Queries are reusable • Static and precompiled queries • Queries as parameters and return values • Queries are extensible
Deconstructing LINQ • Other Language Enhancements • Extension methods • Static methods • Callable on object instances • LINQ query operators are extension methods on IEnumerable<T> or IQueryable<T> • Partial methods • Light-weight event-handling methods • Created by LINQ to SQL code generators • Implementation optional
Deconstructing LINQ • Deferred execution (most queries) • Executes when… • Iteration starts (for each…) • Query accessed with immediate operator • Immediate execution… • Convert query to collection • ToList (), ToArray(), ToDictionary(), ToLookup() • Element access • First(), Single(), ElementAt() • Aggregation operator • Any(), All(), Min(), Max(), Count(), etc.
Deconstructing LINQ • DataContext • Connection and DataReader • Access to tables, views, stored procedures • Entity caching • Change tracking • Concurrency conflict detection • LoadOptions • .LoadWith<> • .AssociateWith<> • Log
Deconstructing LINQ • Viewing the Generated SQL • Debugger • (C# only) ToolTip data display • Immediate window • C#: ?myQuery • VB: ?myQuery.ToString • Console or stream • DataContext.Log (example: Logging.aspx.cs) • What to look for in generated SQL • Parameterized arguments • Select list
Demo & Deconstruction • What Did We Just See? • Retaining query results (like a DataSet) • Filtering a saved query or result • LINQ query-to-objects on result sets • Strong typing using .NET types • Deferred and immediate query execution • DataContext • Debugging LINQ
ORM • Bridging the “impedance mismatch” between object models and relational models • Strong typing • Compiler checking • Intellisense support for your relational model • Integrating queries with objects • No more “Programming in strings” • Builds on existing database • LINQ does not change schema or stored procedures
ORM • Objects, entities, DataSets, and Rows • Row in database is unique • Object is unique • Each ADO.NET query creates a new copy of existing data • LINQ caches query results • “Entity” (object created from database) is unique • Uniqueness constrained to DataContext • LINQ retrieves from cache first, then database
ORM • The visual way • Visual Studio’s drag-and-drop mapping • Easy • Creates DataContext automatically and on-the-fly • Rapid development • Difficult to maintain
ORM • The easy way • SQLMetal • Line command • Creates single file that maps the entire database to objects • Database-specific DataContext • Code generator for your Data Access layer • Mapping can be recreated at any time • Daily build • Any time the schema changes
ORM • SQLMetal • Path • C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin • Syntax • sqlmetal /server:. /database:Northwind /pluralize /views /functions /sprocs /language:cs /code:\NorthwindSchema.cs /namespace:NW.Data
ORM • The hard way • Hand-coded classes • DataContext • Entity classes • Access methods for loading and updating tables from DataContext • Methods for change tracking • Why? • Evolving an existing Data Access layer to use LINQ
ORM • Customizing the DataAccess Layer • Pre-configured DataContexts • Entity caching • Change tracking • Transaction and locking control • Example: NorthwindAccess.cs
ORM • Database issues • Primary keys (required for change tracking and updating) • Foreign keys (useful for associations) • Views (not updatable, even with triggers) • Stored procedures for CRUD • Default LINQ CRUD methods can be overridden to use stored procedures
Putting LINQ to Work • Complex Queries • N-tiered design • Concurrency and conflict resolution • Stored procedures • LINQ to DataSets • Performance
Complex queries • IN clause • Association and foreign keys • Inner Join • Left Join • Non-flat result sets • Using LINQ to query results
N-tiered Design • Layers • Presentation layer • LINQ-based business layer • DataContext as data access layer • Read-only caching • Example: NTierReadOnly.aspx & ProductInfo.cs • Updates, inserts, deletes • Example: NTierCRUD.aspx & Customers.cs
Concurrency & Conflict Resolution • Optimistic Concurrency • ChangeConflictException • Resolve() and ResolveAll() • RefreshMode enumeration • Example: Customers.cs • Pessimistic Concurrency • Use System.Transactions.TransactionScope • Explicit Transaction Control • DataContext.Transaction • See TransActDC() in NorthwindAccess.cs
Stored procedures • One result set • Example: SprocOneResult.aspx • Multiple result sets • Example: SprocTwoResults.aspx • Parameters • Functions • Limitations • No results from temporary tables • No string concatenation for dynamic calls to other stored procedures
LINQ to DataSets • AsEnumerable() converts DataTable to enumeration • Field operators • Field<> • SetField<> • Set operators allow comparison for equality • dt.AsEnumerable().Distinct(DataRowComparer.Default); • Example: DataSetUpdate.aspx • Example: DataSetIntersection.aspx • CopyToDataTable<DataRow>
Performance • Limit what you select • For read-only work, select only columns you need • Deferred loading and immediate loading • Don’t select anonymous classes • Select to entity classes or defined non-entity classes • Static and precompiled queries • Examples: ProductInfo.cs and Customers.cs • Caching
Ticks and Trips • Be careful with null values • Use ? Operator: ((o) => o != null ? o.name : “”) • Use .DefaultIfEmpty(), .FirstOrDefault(), etc. • Use .Count to verify you have results • Nested queries don’t work • Use joins instead • Use DefaultIfEmpty() for left joins • Views aren’t updatable • Use .Cast<>() or .OfType<>() to convert non-generics such as ArrayList
LINQ in the Enterprise • Migration and coexistence • Run LINQ and ADO.NET side-by-side • Use SQL queries and DataReaders in LINQ • ExecuteQuery(), Translate(), ExecuteCommand() • Get results in LINQ entity objects • Concurrency issues • DataContext scope and life cycle • Schema changes • Run SQLMetal as part of every build
References • http://weblogs.asp.net/scottgu/archive/tags/LINQ/default.aspx • http://blogs.msdn.com/ricom/default.aspx • http://www.linqdev.com/ • Rattz, Joseph C., Jr., Pro LINQ Language Integrated Query in C# 2008. Berkeley, CA: Apress, 2007.