├── source ├── 01-GetStarted │ └── SeeVisualStudioProject.txt ├── Assets │ └── ExeEF │ │ ├── Tours.mdf │ │ ├── Tours_log.ldf │ │ ├── ConsoleForEF.exe │ │ ├── ConsoleForEF.pdb │ │ ├── NorthwindV13.MDF │ │ ├── EntityFramework.dll │ │ ├── NorthwindV13_log.ldf │ │ ├── EntityFramework.SqlServer.dll │ │ └── ConsoleForEF.exe.config ├── VisualStudio │ ├── ConsoleForEF │ │ ├── Diagrams │ │ │ ├── ToursDiagram.cd │ │ │ └── LinqTypesDiagram.cd │ │ ├── Tours.mdf │ │ ├── Tours_log.ldf │ │ ├── NorthwindV13.MDF │ │ ├── NorthwindV13_log.ldf │ │ ├── packages.config │ │ ├── ToursModel.cs │ │ ├── NorthwindModel.cs │ │ ├── TravelTip.cs │ │ ├── Testimonial.cs │ │ ├── ToursModel.Designer.cs │ │ ├── NorthwindModel.Designer.cs │ │ ├── ToursModel.edmx.diagram │ │ ├── Program.cs │ │ ├── Order_Detail.cs │ │ ├── Tour.cs │ │ ├── ToursModel.Context.cs │ │ ├── Region.cs │ │ ├── Shipper.cs │ │ ├── Category.cs │ │ ├── Territory.cs │ │ ├── Contact.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Customer.cs │ │ ├── Supplier.cs │ │ ├── NorthwindModel.Context.cs │ │ ├── Product.cs │ │ ├── App.config │ │ ├── Order.cs │ │ ├── Employee.cs │ │ ├── NorthwindModel.edmx.diagram │ │ ├── ToursModel.edmx │ │ ├── ConsoleForEF.csproj │ │ ├── ToursModel.Context.tt │ │ ├── NorthwindModel.Context.tt │ │ └── ToursModel.tt │ └── LinqForDB.sln ├── 02-DB and LINQPad │ ├── 03-Connect To Entity Framework.linq │ ├── 04-View DB structure in UI.linq │ ├── 01-The included sample connection.linq │ └── 02-Connect To Another DB.linq ├── 04-Basic Syntax │ ├── 01-Documentation Links.linq │ ├── 01-Query Basics.linq │ ├── 01-Operator List.linq │ ├── 03B-Extension methods.linq │ ├── 03C-Extension methods.linq │ ├── 02-Enumerable vs Queryable methods.linq │ ├── 03A-Extension methods.linq │ ├── 04C-Query Expression.linq │ ├── 04A-Query Expression.linq │ ├── 04D-Query Expression.linq │ └── 04B-Query Expression.linq ├── 03-Queryable │ ├── 09B-View SQL.linq │ ├── 09A-View SQL.linq │ ├── 08-ExpressionTree.linq │ ├── 07A-Interfaces.linq │ ├── 06A-DbQuery.linq │ ├── 05A-DbSet Add.linq │ ├── 04-DbSet.linq │ ├── 05B-DbSet Remove.linq │ ├── 02-DbContext.linq │ └── 07B-Interfaces.linq ├── OtherExamples │ ├── View Connection Info.linq │ ├── 04-Connection.linq │ ├── 02-SQL.linq │ └── 05-Dataset.linq └── 05-Query Examples │ ├── 04B-Joins.linq │ ├── 04A-Joins.linq │ ├── 07-Flatten with SelectMany.linq │ ├── 06B-Group.linq │ ├── 05-Contains.linq │ ├── 06A-Group.linq │ ├── 01B-Use projection to get less data.linq │ ├── 03-Where and Find.linq │ ├── 01A-Use projection to get less data.linq │ ├── 08-DateRange.linq │ └── 02-Use Take, Skip to page data.linq ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── CONTRIBUTING.md ├── NOTICE ├── README.md ├── LICENSE └── .gitignore /source/01-GetStarted/SeeVisualStudioProject.txt: -------------------------------------------------------------------------------- 1 | Examples are in the Visual Studio folder -------------------------------------------------------------------------------- /source/Assets/ExeEF/Tours.mdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/Tours.mdf -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Diagrams/ToursDiagram.cd: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /source/Assets/ExeEF/Tours_log.ldf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/Tours_log.ldf -------------------------------------------------------------------------------- /source/Assets/ExeEF/ConsoleForEF.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/ConsoleForEF.exe -------------------------------------------------------------------------------- /source/Assets/ExeEF/ConsoleForEF.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/ConsoleForEF.pdb -------------------------------------------------------------------------------- /source/Assets/ExeEF/NorthwindV13.MDF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/NorthwindV13.MDF -------------------------------------------------------------------------------- /source/Assets/ExeEF/EntityFramework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/EntityFramework.dll -------------------------------------------------------------------------------- /source/Assets/ExeEF/NorthwindV13_log.ldf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/NorthwindV13_log.ldf -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Tours.mdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/VisualStudio/ConsoleForEF/Tours.mdf -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Tours_log.ldf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/VisualStudio/ConsoleForEF/Tours_log.ldf -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Codeowners for these exercise files: 2 | # * (asterisk) deotes "all files and folders" 3 | # Example: * @producer @instructor 4 | -------------------------------------------------------------------------------- /source/Assets/ExeEF/EntityFramework.SqlServer.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/Assets/ExeEF/EntityFramework.SqlServer.dll -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/NorthwindV13.MDF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/VisualStudio/ConsoleForEF/NorthwindV13.MDF -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/NorthwindV13_log.ldf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/linq-to-db/HEAD/source/VisualStudio/ConsoleForEF/NorthwindV13_log.ldf -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /source/02-DB and LINQPad/03-Connect To Entity Framework.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | // An Entity Framework source is comprised of .NET mapping classes 4 | // Connections to EF classes in LINQPad are done by using the .NET exe or dll that contains the types 5 | 6 | 7 | // for this course, we'll use the ConsoleForEF.exe executable. -------------------------------------------------------------------------------- /source/04-Basic Syntax/01-Documentation Links.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Read more about Query Operators at Microsoft docs. 4 | 5 | // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/query-expression-syntax-for-standard-query-operators 6 | 7 | // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/standard-query-operators-overview -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ToursModel.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/NorthwindModel.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | -------------------------------------------------------------------------------- /source/02-DB and LINQPad/04-View DB structure in UI.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | 54bf9502-9daf-4093-88e8-7177c129999f 4 | 2 5 | System.Data.SqlServerCe.4.0 6 | <ApplicationData>\LINQPad\DemoDB.sdf 7 | true 8 | true 9 | 10 | 11 | 12 | // View the DB tables 13 | // and Entity Framework types in the Connection pane on left -------------------------------------------------------------------------------- /source/04-Basic Syntax/01-Query Basics.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | // LINQ query operators are implemented as Extension methods... 4 | 5 | // Call via the 'method syntax', pass in lambda expressions as parameters 6 | // Use Linq Query Expression 7 | 8 | // source.Where (predicateExpression); 9 | 10 | // Or use the LINQ query expression syntax 11 | 12 | // from s in source 13 | // where predicateExpression 14 | // select s; 15 | 16 | // Calls via the 'query syntax', 17 | // are converted to method syntax 18 | 19 | 20 | // Learn more about LINQ 21 | // https://www.linkedin.com/learning/topics/linq 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | Contribution Agreement 3 | ====================== 4 | 5 | This repository does not accept pull requests (PRs). All pull requests will be closed. 6 | 7 | However, if any contributions (through pull requests, issues, feedback or otherwise) are provided, as a contributor, you represent that the code you submit is your original work or that of your employer (in which case you represent you have the right to bind your employer). By submitting code (or otherwise providing feedback), you (and, if applicable, your employer) are licensing the submitted code (and/or feedback) to LinkedIn and the open source community subject to the BSD 2-Clause license. 8 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2021 LinkedIn Corporation 2 | All Rights Reserved. 3 | 4 | Licensed under the LinkedIn Learning Exercise File License (the "License"). 5 | See LICENSE in the project root for license information. 6 | 7 | Please note, this project may automatically load third party code from external 8 | repositories (for example, NPM modules, Composer packages, or other dependencies). 9 | If so, such third party code may be subject to other license terms than as set 10 | forth above. In addition, such third party code may also depend on and load 11 | multiple tiers of dependencies. Please review the applicable licenses of the 12 | additional dependencies. 13 | -------------------------------------------------------------------------------- /source/02-DB and LINQPad/01-The included sample connection.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | // LINQPad includes a sample SQLCE (Compact Edition) database 4 | 5 | // It's installed at C:\Users[current user]\AppData\Roaming\LINQPad 6 | // It's added as a sample database connection in the connection panel (on left). 7 | 8 | // The database (DemoDB.sdf) requires SQL CE. The first time you expand the connection, 9 | // LINQPad will ask if want to download the NuGet package for SQL CE 10 | // if the package is not in the Visual Studio NuGet cache. 11 | 12 | 13 | // LINQPad 6 targets .NET Core 3 and .NET 5 for Windows. 14 | // LINQPad 5 Targets .NET Framework -------------------------------------------------------------------------------- /source/03-Queryable/09B-View SQL.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | 11 | 12 | Shippers.Dump(); 13 | 14 | var q1 = from s in Shippers 15 | select s; 16 | 17 | q1.Dump(); -------------------------------------------------------------------------------- /source/04-Basic Syntax/01-Operator List.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Lots of Extension methods, similar to what is available for LINQ to Objects 4 | 5 | // [Basics] 6 | // Select, Where, Orderby 7 | 8 | // [Aggregates] 9 | // Sum, Average, Count, Min, Max 10 | 11 | // [Sets] 12 | // Union, Intersect, Distinct, Except 13 | 14 | // [Quantifiers] 15 | // All, Any, Contains 16 | 17 | // [Partitions] 18 | // Skip, Take, SkipWhile, TakeWhile 19 | 20 | // [Groups] 21 | // GroupBy, ToLookup 22 | 23 | // [Elements] 24 | // First, Last, ElementAt, Single, FirstOrDefault... 25 | 26 | // [Joins] 27 | // Join, GroupJoin 28 | 29 | // Learn more about LINQ 30 | // https://www.linkedin.com/learning/topics/linq 31 | -------------------------------------------------------------------------------- /source/02-DB and LINQPad/02-Connect To Another DB.linq: -------------------------------------------------------------------------------- 1 | 2 | System.Numerics 3 | 4 | 5 | // add connections to 6 | // SQL Server, SQL Azure, SQL CE, Oracle, SQLite, PostgreSQL and MySQL 7 | // Azure Table Storage & Azure Metadata 8 | // Entity Framework Core custom contexts 9 | // Microsoft Reactive Extensions and LINQ to Logs & Traces 10 | // OData and SharePoint 11 | // Third - party ORMs: Mindscape LightSpeed, DevArt’s LinqConnect, LLBLGen, 12 | // DevExpress eXpress Persistent Objects and DevForce 13 | 14 | 15 | 16 | // LINQPad 6 targets .NET Core 3 and .NET 5 for Windows. 17 | // LINQPad 5 Targets .NET Framework 18 | 19 | // Connect to (localdb)\MSSQLLocalDB 20 | // -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/TravelTip.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class TravelTip 16 | { 17 | public int TipId { get; set; } 18 | public string Headline { get; set; } 19 | public string TipText { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/03-Queryable/09A-View SQL.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | 11 | 12 | // Use the SQL property to get the SQL used for the query 13 | 14 | Categories.Sql.Dump(); 15 | Categories.ToString().Dump(); // ToString works too! 16 | 17 | var q1 = from s in Shippers 18 | select s; 19 | q1.ToString().Dump(); 20 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Testimonial.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Testimonial 16 | { 17 | public int TestimonialId { get; set; } 18 | public string CustomerName { get; set; } 19 | public string Comment { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/04-Basic Syntax/03B-Extension methods.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | 11 | 12 | // Extension methods 13 | 14 | // Pipeline the extension methods. 15 | 16 | var orderedResults = Products.OrderBy(p => p.ProductName); 17 | 18 | var pipelinedResults = orderedResults.Where(p => p.UnitsInStock == 0); 19 | 20 | 21 | pipelinedResults.Dump(); -------------------------------------------------------------------------------- /source/04-Basic Syntax/03C-Extension methods.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | 11 | 12 | // Extension methods 13 | 14 | // Pipeline the extension methods. 15 | 16 | var pipelinedResults = Products.OrderBy(p => p.UnitPrice ) 17 | .Where(p => p.UnitsInStock ==0 ) 18 | .Select(p => p.ProductName); 19 | 20 | pipelinedResults.Dump(); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ToursModel.Designer.cs: -------------------------------------------------------------------------------- 1 | // T4 code generation is enabled for model 'C:\Users\WR\Source\Repos\linq-databases-2858036\source\VisualStudio\ConsoleForEF\ToursModel.edmx'. 2 | // To enable legacy code generation, change the value of the 'Code Generation Strategy' designer 3 | // property to 'Legacy ObjectContext'. This property is available in the Properties Window when the model 4 | // is open in the designer. 5 | 6 | // If no context and entity classes have been generated, it may be because you created an empty model but 7 | // have not yet chosen which version of Entity Framework to use. To generate a context class and entity 8 | // classes for your model, open the model in the designer, right-click on the designer surface, and 9 | // select 'Update Model from Database...', 'Generate Database from Model...', or 'Add Code Generation 10 | // Item...'. -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/NorthwindModel.Designer.cs: -------------------------------------------------------------------------------- 1 | // T4 code generation is enabled for model 'C:\Users\WR\Source\Repos\linq-databases-2858036\source\VisualStudio\ConsoleForEF\NorthwindModel.edmx'. 2 | // To enable legacy code generation, change the value of the 'Code Generation Strategy' designer 3 | // property to 'Legacy ObjectContext'. This property is available in the Properties Window when the model 4 | // is open in the designer. 5 | 6 | // If no context and entity classes have been generated, it may be because you created an empty model but 7 | // have not yet chosen which version of Entity Framework to use. To generate a context class and entity 8 | // classes for your model, open the model in the designer, right-click on the designer surface, and 9 | // select 'Update Model from Database...', 'Generate Database from Model...', or 'Add Code Generation 10 | // Item...'. -------------------------------------------------------------------------------- /source/OtherExamples/View Connection Info.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | 54bf9502-9daf-4093-88e8-7177c129999f 4 | 2 5 | System.Data.SqlServerCe.4.0 6 | <ApplicationData>\LINQPad\DemoDB.sdf 7 | true 8 | true 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var ctx = this; 14 | 15 | //ctx.Dump(); 16 | ctx.Shippers.GetType().FullName.Dump(); 17 | ctx.Connection.Open(); 18 | ctx.Connection.Dump(); 19 | ctx.GetType().BaseType.BaseType.BaseType.Dump(); 20 | ctx.Connection.Close(); -------------------------------------------------------------------------------- /source/04-Basic Syntax/02-Enumerable vs Queryable methods.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | 11 | 12 | var colors = new List 13 | { "Green", "Blush", "Yellow", "Red", "Orange", 14 | "Burgandy", "Purple", "White", "Black", "Blue" ,"Bronze"}; 15 | 16 | var q1 = colors.Where(c => c.StartsWith("B") ); 17 | q1.Dump(); 18 | 19 | var q2 = Products.Where(p => p.ProductName.StartsWith("F")); 20 | q2.Dump(); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ToursModel.edmx.diagram: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ConsoleForEF 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | // get the Entity Framework (EF) data context 14 | // using the default connection defined in the app.config file 15 | var context = new NorthwindEntities(); 16 | 17 | // work with the EF model classes 18 | 19 | var shipper = context.Shippers.First(); 20 | 21 | Console.WriteLine(shipper.CompanyName); 22 | 23 | //var products = from p in context.Products 24 | // where p.UnitPrice < 20 25 | // select new { p.ProductName, p.UnitPrice }; 26 | 27 | //foreach (var product in products) 28 | //{ 29 | // Console.WriteLine($"{product.ProductName}, {product.UnitPrice} "); 30 | //} 31 | 32 | 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /source/04-Basic Syntax/03A-Extension methods.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | 11 | 12 | // Extension methods 13 | 14 | // Call a single extension method 15 | 16 | var orderedResults = Products.OrderBy(p => p.ProductName); 17 | 18 | var filteredResults = Products.Where(p => p.UnitsInStock == 0); 19 | 20 | orderedResults.Dump(); 21 | filteredResults.Dump(); 22 | 23 | // Learn more about LINQ 24 | // https://www.linkedin.com/learning/topics/linq -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Order_Detail.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Order_Detail 16 | { 17 | public int OrderID { get; set; } 18 | public int ProductID { get; set; } 19 | public decimal UnitPrice { get; set; } 20 | public short Quantity { get; set; } 21 | public float Discount { get; set; } 22 | 23 | public virtual Order Order { get; set; } 24 | public virtual Product Product { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source/05-Query Examples/04B-Joins.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | System.Data.Entity 11 | 12 | 13 | // The DB joins are defined in the EF mapping 14 | // this simplifies common queries. 15 | 16 | 17 | 18 | var q2 = from o in Order_Details 19 | where o.Order.CustomerID == "ISLAT" 20 | select new {o.Order.Customer.CompanyName, o.Order.OrderDate, 21 | o.Product.ProductName, Employee= o.Order.Employee.FirstName + " " + o.Order.Employee.LastName }; 22 | 23 | q2.Take (10).Dump(); -------------------------------------------------------------------------------- /source/OtherExamples/04-Connection.linq: -------------------------------------------------------------------------------- 1 | 2 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\DB\System.Data.SqlServerCe.dll 3 | System.Data.SqlClient 4 | System.Numerics 5 | 6 | 7 | // LINQPad provides an easy way to get data context for a database 8 | // this example bypasses the LINQPad system and uses basic ADO.NET 9 | // Note: since this is .NET core 10 | // add System.Data.Common and System.Data.SqlClient nuget packages. 11 | void Main() 12 | { 13 | var ds = new DataSet(); 14 | OpenDBConnection(); 15 | } 16 | 17 | // You can define other methods, fields, classes and namespaces here 18 | void OpenDBConnection() 19 | { 20 | 21 | 22 | string cnString = @"data source='C:\Users\WR\AppData\Roaming\LINQPad\DemoDB.sdf'"; 23 | 24 | using (var conn = new System.Data.SqlServerCe.SqlCeConnection(cnString)) 25 | { 26 | conn.Open(); 27 | 28 | conn.Dump(); 29 | conn.Close(); 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /source/05-Query Examples/04A-Joins.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | 11 | 12 | // The DB joins are defined in the EF mapping 13 | // In the entity classes they are represented as Navigation properties. 14 | // Navigation properties provide a way to navigate an association between two entity types 15 | // They allow you to navigate and manage relationships in both directions 16 | 17 | // this simplifies common LINQ queries. 18 | 19 | 20 | 21 | var q2 = from o in Order_Details 22 | where o.Order.CustomerID =="ISLAT" 23 | select o; 24 | 25 | q2.Dump(); -------------------------------------------------------------------------------- /source/03-Queryable/08-ExpressionTree.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var context = new NorthwindEntities(); 14 | 15 | var q1 = from r in context.Regions 16 | where r.RegionID == 2 17 | select r; 18 | 19 | q1.Dump(); 20 | 21 | // View the query provider. 22 | q1.Provider.ToString().Dump(); 23 | // View the expression tree 24 | 25 | q1.Expression.Dump(); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Tour.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Tour 16 | { 17 | public int TourId { get; set; } 18 | public string TourName { get; set; } 19 | public Nullable SeniorDiscountAvailable { get; set; } 20 | public Nullable KidFriendly { get; set; } 21 | public Nullable MultiDay { get; set; } 22 | public string Region { get; set; } 23 | public Nullable MaxPeoplePerTour { get; set; } 24 | public string TourImagePath { get; set; } 25 | public string Description { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/03-Queryable/07A-Interfaces.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var context = new NorthwindEntities(); 14 | // Products is DbSet 15 | context.Products.GetType().Name.Dump("Products property is DbSet"); 16 | 17 | // this query is DbQuery 18 | var q = from p in Products 19 | select p; 20 | 21 | q.GetType().Name.Dump("The query is DbQuery"); 22 | Products.Select(p => p).GetType().Name.Dump("DbQuery from Extension method"); 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | ## Issue Overview 9 | 10 | 11 | ## Describe your environment 12 | 13 | 14 | ## Steps to Reproduce 15 | 16 | 1. 17 | 2. 18 | 3. 19 | 4. 20 | 21 | ## Expected Behavior 22 | 23 | 24 | ## Current Behavior 25 | 26 | 27 | ## Possible Solution 28 | 29 | 30 | ## Screenshots / Video 31 | 32 | 33 | ## Related Issues 34 | 35 | -------------------------------------------------------------------------------- /source/04-Basic Syntax/04C-Query Expression.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // instead of pipelining, add clauses to query expression 14 | var manyClauses = from p in Products 15 | orderby p.UnitPrice 16 | where p.UnitsInStock == 0 17 | select p.ProductName; 18 | 19 | 20 | 21 | manyClauses.Dump(); 22 | 23 | 24 | 25 | 26 | // Learn more about LINQ 27 | // https://www.linkedin.com/learning/topics/linq -------------------------------------------------------------------------------- /source/05-Query Examples/07-Flatten with SelectMany.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | c54576d1-888b-4050-976b-0c662e22b616 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // SelectMany flattens a one-many relationship 14 | // or saying it another way , it can ungroup nested sequences 15 | 16 | 17 | Regions.Dump(); 18 | var q1 = from r in Regions 19 | select r.Territories; 20 | q1.Dump("4 hashset collections in result"); 21 | var q2 = Regions.SelectMany(r =>r.Territories); 22 | 23 | q2.Dump("Flattened to a single DbQuery"); -------------------------------------------------------------------------------- /source/04-Basic Syntax/04A-Query Expression.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // Query expression syntax 14 | // a pass through query, returns all rows and columns 15 | // same as SELECT * FROM TABLE_NAME in SQL 16 | 17 | 18 | var q1 = from s in Shippers 19 | select s; 20 | var q2 = from t in Territories 21 | select t; 22 | q1.Dump(); 23 | q2.Dump(); 24 | 25 | 26 | 27 | // Learn more about LINQ 28 | // https://www.linkedin.com/learning/topics/linq -------------------------------------------------------------------------------- /source/05-Query Examples/06B-Group.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | c54576d1-888b-4050-976b-0c662e22b616 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // group by ship country 14 | 15 | 16 | var q = from o in Orders 17 | group o by o.ShipCountry into shipGroup 18 | select new { shipGroup.Key, Total = shipGroup.Sum(o => o.Freight) } into totalItem 19 | orderby totalItem.Total, totalItem.Key 20 | select new { TotalShipCost = totalItem.Total, Country = totalItem.Key }; 21 | 22 | q.Dump("Orders grouped by ship country showing total:"); -------------------------------------------------------------------------------- /source/05-Query Examples/05-Contains.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | 14 | // use results of a query as arguments to another query 15 | 16 | 17 | var q1 = from p in Products 18 | where p.UnitPrice > 90 19 | select p.ProductID; 20 | 21 | q1.Dump(); 22 | 23 | Order_Details.Take(10).Dump(); 24 | 25 | var productIds= q1.ToList(); 26 | var q2 = from o in Order_Details 27 | 28 | where productIds.Contains(o.Product.ProductID) 29 | select o; 30 | q2.Dump(); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ToursModel.Context.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Data.Entity; 14 | using System.Data.Entity.Infrastructure; 15 | 16 | public partial class ToursEntities : DbContext 17 | { 18 | public ToursEntities() 19 | : base("name=ToursEntities") 20 | { 21 | } 22 | 23 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 24 | { 25 | throw new UnintentionalCodeFirstException(); 26 | } 27 | 28 | public virtual DbSet Testimonials { get; set; } 29 | public virtual DbSet Tours { get; set; } 30 | public virtual DbSet TravelTips { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /source/VisualStudio/LinqForDB.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30413.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleForEF", "ConsoleForEF\ConsoleForEF.csproj", "{576E8704-2FFB-4211-9AE9-2CE09902ED87}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {576E8704-2FFB-4211-9AE9-2CE09902ED87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {576E8704-2FFB-4211-9AE9-2CE09902ED87}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {576E8704-2FFB-4211-9AE9-2CE09902ED87}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {576E8704-2FFB-4211-9AE9-2CE09902ED87}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {502DB44D-7775-46D8-97EE-C48C71138FC9} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Region.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Region 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Region() 19 | { 20 | this.Territories = new HashSet(); 21 | } 22 | 23 | public int RegionID { get; set; } 24 | public string RegionDescription { get; set; } 25 | 26 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 27 | public virtual ICollection Territories { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Diagrams/LinqTypesDiagram.cd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /source/03-Queryable/06A-DbQuery.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var context = new NorthwindEntities(); 14 | 15 | // DbSet and DbQuery implement IQueryable 16 | // DbQuery represents a non-generic LINQ to Entities query against a DbContext. (EF 6.x) 17 | // EF Core 2.1, useful to represent non-updateable database Views 18 | // EF Core 3, removed from EF 19 | 20 | // EF 6 21 | 22 | context.Regions.Dump(); 23 | var q1 = from r in context.Regions 24 | where r.RegionID == 2 25 | select r; 26 | q1.Dump (); -------------------------------------------------------------------------------- /source/05-Query Examples/06A-Group.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | c54576d1-888b-4050-976b-0c662e22b616 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | 14 | 15 | var q1 = from p in Products 16 | select new {p.ProductName, p.UnitPrice}; 17 | q1.Dump(); 18 | 19 | var q2 = from p in Products 20 | group p by p.ProductName.Substring(0,1) into g 21 | select g; 22 | q2.Dump(); 23 | 24 | var q3 = from p in Products 25 | select new {p.ProductName, p.UnitPrice} into pGroup 26 | group pGroup by pGroup.ProductName.Substring(0, 1) into g 27 | select g; 28 | q3.Dump(); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Shipper.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Shipper 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Shipper() 19 | { 20 | this.Orders = new HashSet(); 21 | } 22 | 23 | public int ShipperID { get; set; } 24 | public string CompanyName { get; set; } 25 | public string Phone { get; set; } 26 | 27 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 28 | public virtual ICollection Orders { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /source/05-Query Examples/01B-Use projection to get less data.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var context = new NorthwindEntities(); 14 | // use where to filter the number of rows returned 15 | // use projection (via select) to filter the number of columns returned 16 | 17 | // Extension method syntax 18 | var q1 = Customers.Where(c => c.City.StartsWith("S")); 19 | 20 | q1.Dump(); 21 | 22 | var q2 = Customers.Where(c => c.City.StartsWith("S")).Select (c=>new { c.CompanyName, c.Address, c.City}); 23 | 24 | q2.Dump(); -------------------------------------------------------------------------------- /source/03-Queryable/05A-DbSet Add.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var context = new NorthwindEntities(); 14 | 15 | // DbSet instance is a in memory collection 16 | // filled from the database 17 | 18 | // changes to items in the DbSet are not commited to DB, unless .SaveChanges is called. 19 | 20 | var nwRegion = new Region { RegionID = 44, RegionDescription = "NorthWest" }; 21 | 22 | context.Regions.Dump("Before Add"); 23 | context.Regions.Add(nwRegion); 24 | //context.SaveChanges(); 25 | context.Regions.Dump("After Add"); -------------------------------------------------------------------------------- /source/03-Queryable/04-DbSet.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | c54576d1-888b-4050-976b-0c662e22b616 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var context = new NorthwindEntities(); 14 | 15 | // DbSet and DbQuery implement IQueryable 16 | // DbSet represents the EF model for a database table 17 | 18 | // Regions table in EF ORM is mapped to the DbContext.Regions property 19 | // public virtual DbSet Regions { get; set; } 20 | // a row in the Regions table is mapped to the Region class 21 | 22 | context.Regions.Dump(); 23 | var regionRow = context.Regions.First(); 24 | regionRow.Dump(); 25 | 26 | -------------------------------------------------------------------------------- /source/03-Queryable/05B-DbSet Remove.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var context = new NorthwindEntities(); 14 | 15 | // DbSet instance is a in memory collection 16 | // filled from the database 17 | 18 | // changes to items in the DbSet are not commited to DB, unless .SaveChanges is called. 19 | 20 | var nwRegion = context.Regions.Where(r => r.RegionID==44 ).Single(); 21 | context.Regions.Dump("Before Remove"); 22 | context.Regions.Remove(nwRegion); 23 | 24 | //context.SaveChanges(); 25 | context.Regions.Dump("After Remove"); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Category.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Category 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Category() 19 | { 20 | this.Products = new HashSet(); 21 | } 22 | 23 | public int CategoryID { get; set; } 24 | public string CategoryName { get; set; } 25 | public string Description { get; set; } 26 | public byte[] Picture { get; set; } 27 | 28 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 29 | public virtual ICollection Products { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /source/05-Query Examples/03-Where and Find.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // Use Find to get an entity with the specified key value 14 | // This is faster if item is cached in the context (DbContext in this example). 15 | 16 | // Microsoft Docs: Find is different from using a query: 17 | // A round-trip to the database happens if the entity 18 | // with the given key is not found in the context. 19 | 20 | 21 | Products.Where(p => p.ProductID == 4).Single().Dump(); 22 | Products.Where(p => p.ProductID == 4).Single().Dump(); 23 | //Products.Find(4).Dump(); 24 | //Products.Find(4).Dump(); -------------------------------------------------------------------------------- /source/04-Basic Syntax/04D-Query Expression.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // instead of pipelining, add clauses to query expression 14 | var manyClauses = from p in Products 15 | orderby p.UnitPrice 16 | where p.UnitsInStock == 0 17 | select p.ProductName; 18 | 19 | 20 | 21 | manyClauses.Dump(); 22 | 23 | // some operators, like Count, cannot be used in the query expression! 24 | // call them on the query variable 25 | 26 | manyClauses.Count().Dump("Call Count method"); 27 | 28 | // Learn more about LINQ 29 | // https://www.linkedin.com/learning/topics/linq -------------------------------------------------------------------------------- /source/05-Query Examples/01A-Use projection to get less data.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // Where clause filters the number of rows returned 14 | // Select clause (aka projection) filters the number of columns returned 15 | 16 | Customers.Count().Dump("# rows in Customers"); 17 | var q1 = from c in Customers 18 | where c.City.StartsWith ("S") 19 | select c; 20 | 21 | // check the generated SQL, this gets all columns 22 | q1.Dump (); 23 | 24 | var q2 = from c in Customers 25 | where c.City.StartsWith ("S") 26 | select new {c.CompanyName, c.Address, c.City}; 27 | q2.Dump(); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Territory.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Territory 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Territory() 19 | { 20 | this.Employees = new HashSet(); 21 | } 22 | 23 | public string TerritoryID { get; set; } 24 | public string TerritoryDescription { get; set; } 25 | public int RegionID { get; set; } 26 | 27 | public virtual Region Region { get; set; } 28 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 29 | public virtual ICollection Employees { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /source/05-Query Examples/08-DateRange.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // get orders in date range 14 | 15 | TimeSpan thirtyDays = TimeSpan.FromDays(30); 16 | 17 | // get an order 18 | var q1 = from o in Orders 19 | where o.OrderID == 10250 20 | select new {o.OrderID, o.OrderDate, o.ShipName}; 21 | 22 | q1.Take(1).Dump(); 23 | 24 | var originalDate = q1.First().OrderDate; 25 | var futureDate = originalDate + thirtyDays; 26 | var q2= from o in Orders 27 | where o.OrderDate > originalDate & o.OrderDate < futureDate 28 | select new {o.OrderID, o.OrderDate, o.ShipName}; 29 | 30 | q2.Dump(); -------------------------------------------------------------------------------- /source/05-Query Examples/02-Use Take, Skip to page data.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // use Take/Skip to get less rows without a where clause 14 | // Take: Returns contiguous elements from the start of a sequence. 15 | // Skip: Bypasses elements in a sequence and then returns the remaining elements. 16 | var q1 = from p in Products 17 | orderby p.ProductID 18 | select new {p.ProductID, p.ProductName, p.UnitPrice}; 19 | 20 | var count = q1.Count(); 21 | 22 | count.Dump("Products count"); 23 | 24 | var pageSize = 5; 25 | q1.Take(pageSize).Dump("First page"); 26 | q1.Skip(pageSize).Take (pageSize).Dump("Next page"); -------------------------------------------------------------------------------- /source/03-Queryable/02-DbContext.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | 14 | // DbContext represents a session with a database 15 | // it is responsible for opening and closing the database connection 16 | 17 | // it manages change tracking, so that it know what SQL to generate 18 | // for updates, deletes and inserts. 19 | 20 | // it supports caching, so that subsequent request for same data hits the cache. 21 | 22 | // it uses transactions when SaveChanges is called. 23 | 24 | var context = new NorthwindEntities(); 25 | 26 | var type = context.GetType(); 27 | type.FullName.Dump("Context Type"); 28 | type.BaseType.FullName.Dump("Base Type"); -------------------------------------------------------------------------------- /source/04-Basic Syntax/04B-Query Expression.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | // Add more clauses 14 | 15 | 16 | var allProducts = from p in Products 17 | select p; 18 | var filteredProducts = from p in Products 19 | where p.UnitsInStock ==0 20 | select p; 21 | 22 | var orderedProducts = from p in Products 23 | orderby p.UnitPrice 24 | select p; 25 | 26 | // instead of pipelining, add clauses to query expression 27 | 28 | allProducts.Dump(); 29 | filteredProducts.Dump(); 30 | orderedProducts.Dump(); 31 | 32 | 33 | 34 | // Learn more about LINQ 35 | // https://www.linkedin.com/learning/topics/linq -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Contact.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Contact 16 | { 17 | public int ContactID { get; set; } 18 | public string ContactType { get; set; } 19 | public string CompanyName { get; set; } 20 | public string ContactName { get; set; } 21 | public string ContactTitle { get; set; } 22 | public string Address { get; set; } 23 | public string City { get; set; } 24 | public string Region { get; set; } 25 | public string PostalCode { get; set; } 26 | public string Country { get; set; } 27 | public string Phone { get; set; } 28 | public string Extension { get; set; } 29 | public string Fax { get; set; } 30 | public string HomePage { get; set; } 31 | public string PhotoPath { get; set; } 32 | public byte[] Photo { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /source/OtherExamples/02-SQL.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | 54bf9502-9daf-4093-88e8-7177c129999f 4 | 2 5 | System.Data.SqlServerCe.4.0 6 | <ApplicationData>\LINQPad\DemoDB.sdf 7 | true 8 | true 9 | 10 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\DB\System.Data.SqlServerCe.dll 11 | System.Data.SqlClient 12 | System.Data.SqlServerCe 13 | System.Numerics 14 | 15 | 16 | void Main() 17 | { 18 | // Represents the main entry point for the LINQ to SQL framework. 19 | string cnString = @"data source='C:\Users\WR\AppData\Roaming\LINQPad\DemoDB.sdf'"; 20 | 21 | using (var conn = new System.Data.SqlServerCe.SqlCeConnection(cnString)) 22 | { 23 | conn.Open(); 24 | 25 | var context = GetDataContext(conn); 26 | 27 | context. 28 | conn.Close(); 29 | 30 | } 31 | 32 | 33 | } 34 | 35 | // Define other methods and classes here 36 | public DataContext GetDataContext (SqlCeConnection conn) 37 | { 38 | var myContext = new DataContext(conn,); 39 | var product = context.Products.Where(p => p.Id == productId).SingleOrDefault(); 40 | return null; 41 | } -------------------------------------------------------------------------------- /source/OtherExamples/05-Dataset.linq: -------------------------------------------------------------------------------- 1 | 2 | <ProgramFilesX86>\Microsoft Visual Studio\Shared\Packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll 3 | System.Data.SqlClient 4 | System.Data.SqlServerCe 5 | System.Numerics 6 | 7 | 8 | // LINQPad provides an easy way to get data context for a database 9 | // this example bypasses the LINQPad system and uses basic ADO.NET 10 | // Note: since this is .NET core 11 | // add System.Data.Common and System.Data.SqlClient nuget packages. 12 | void Main() 13 | { 14 | 15 | string cnString = @"data source='C:\Users\WR\AppData\Roaming\LINQPad\DemoDB.sdf'"; 16 | 17 | 18 | using (var conn = new System.Data.SqlServerCe.SqlCeConnection(cnString)) 19 | { 20 | conn.Open(); 21 | 22 | var ds = GetDataSet (conn); 23 | 24 | ds.Dump(); 25 | conn.Close(); 26 | 27 | } 28 | 29 | } 30 | 31 | 32 | public DataSet GetDataSet(SqlCeConnection conn) 33 | { 34 | var dataSet = new DataSet("NorthwindDemo"); 35 | var shippersAdapter= new SqlCeDataAdapter("Select * From Shippers", conn); 36 | shippersAdapter.Fill(dataSet, "Shippers"); 37 | var productsAdapter = new SqlCeDataAdapter("Select [Product Name],[Unit Price], [Units In Stock]From Products ", conn); 38 | productsAdapter.Fill(dataSet, "Products"); 39 | 40 | 41 | return dataSet; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /source/03-Queryable/07B-Interfaces.linq: -------------------------------------------------------------------------------- 1 | 2 | 3 | aef7d1f3-9ecd-4b72-8ac7-667df71c9301 4 | true 5 | EntityFrameworkDbContext 6 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe 7 | ConsoleForEF.NorthwindEntities 8 | C:\Users\WR\Source\Repos\linq-databases-2858036\source\Assets\ExeEF\ConsoleForEF.exe.config 9 | 10 | C:\Users\WR\Source\Repos\linq-2833070\source\VisualStudio\CourseLib\bin\Debug\netstandard2.0\CourseLib.dll 11 | 12 | 13 | var numbers = new List { 3, 5, 7, 9, 11 }; 14 | var q1 = from n in numbers 15 | where n < 20 16 | select n; 17 | 18 | q1.Dump("Linq to Objects query"); 19 | // The where clause uses the Enumerable.Where 20 | // Implmented via an anonymous method 21 | q1.ToString().Dump("Using the Enumerable Where"); 22 | 23 | // LINQ to EF queries types with IQueryable 24 | // LINQ to EF creates an expression tree 25 | // Uses the Queryable.Where 26 | 27 | var q2 = from p in Products 28 | where p.UnitPrice > 100 29 | select new { p.ProductName, p.UnitPrice }; 30 | 31 | q2.Dump("Linq to EF, query"); 32 | q2.GetType().GetInterfaces().Dump("DbQuery interfaces"); 33 | 34 | q2.ToString().Dump("Using the Where"); 35 | q2.Expression.Dump(); -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ConsoleForEF")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ConsoleForEF")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("576e8704-2ffb-4211-9ae9-2ce09902ed87")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Customer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Customer 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Customer() 19 | { 20 | this.Orders = new HashSet(); 21 | } 22 | 23 | public string CustomerID { get; set; } 24 | public string CompanyName { get; set; } 25 | public string ContactName { get; set; } 26 | public string ContactTitle { get; set; } 27 | public string Address { get; set; } 28 | public string City { get; set; } 29 | public string Region { get; set; } 30 | public string PostalCode { get; set; } 31 | public string Country { get; set; } 32 | public string Phone { get; set; } 33 | public string Fax { get; set; } 34 | 35 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 36 | public virtual ICollection Orders { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Supplier.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Supplier 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Supplier() 19 | { 20 | this.Products = new HashSet(); 21 | } 22 | 23 | public int SupplierID { get; set; } 24 | public string CompanyName { get; set; } 25 | public string ContactName { get; set; } 26 | public string ContactTitle { get; set; } 27 | public string Address { get; set; } 28 | public string City { get; set; } 29 | public string Region { get; set; } 30 | public string PostalCode { get; set; } 31 | public string Country { get; set; } 32 | public string Phone { get; set; } 33 | public string Fax { get; set; } 34 | public string HomePage { get; set; } 35 | 36 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 37 | public virtual ICollection Products { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/NorthwindModel.Context.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Data.Entity; 14 | using System.Data.Entity.Infrastructure; 15 | 16 | public partial class NorthwindEntities : DbContext 17 | { 18 | public NorthwindEntities() 19 | : base("name=NorthwindEntities") 20 | { 21 | } 22 | 23 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 24 | { 25 | throw new UnintentionalCodeFirstException(); 26 | } 27 | 28 | public virtual DbSet Categories { get; set; } 29 | public virtual DbSet Contacts { get; set; } 30 | public virtual DbSet Customers { get; set; } 31 | public virtual DbSet Employees { get; set; } 32 | public virtual DbSet Order_Details { get; set; } 33 | public virtual DbSet Orders { get; set; } 34 | public virtual DbSet Products { get; set; } 35 | public virtual DbSet Regions { get; set; } 36 | public virtual DbSet Shippers { get; set; } 37 | public virtual DbSet Suppliers { get; set; } 38 | public virtual DbSet Territories { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Product.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Product 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Product() 19 | { 20 | this.Order_Details = new HashSet(); 21 | } 22 | 23 | public int ProductID { get; set; } 24 | public string ProductName { get; set; } 25 | public Nullable SupplierID { get; set; } 26 | public Nullable CategoryID { get; set; } 27 | public string QuantityPerUnit { get; set; } 28 | public Nullable UnitPrice { get; set; } 29 | public Nullable UnitsInStock { get; set; } 30 | public Nullable UnitsOnOrder { get; set; } 31 | public Nullable ReorderLevel { get; set; } 32 | public bool Discontinued { get; set; } 33 | 34 | public virtual Category Category { get; set; } 35 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 36 | public virtual ICollection Order_Details { get; set; } 37 | public virtual Supplier Supplier { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/Assets/ExeEF/ConsoleForEF.exe.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # .NET Essentials: LINQ for Databases 2 | This is the repository for the LinkedIn Learning course .NET Essentials: LINQ for Databases. The full course is available from [LinkedIn Learning][lil-course-url]. 3 | 4 | ![.NET Essentials: LINQ for Databases][lil-thumbnail-url] 5 | The first explanation you typically hear about Microsoft LINQ is that it provides an in-language query tool to manipulate the contents of arrays and lists. Explore LINQ further and you’ll find it works with other popular data sources like databases and XML files. That makes it a universal query tool that simplifies working with any data source. In this course, part of a three-course series, LinkedIn Learning staff author Walt Ritscher uses LINQPad, a lightweight, powerful code editor, to illustrate useful topics like queryable types, basic query syntax, finding data by date range, and how to use LINQ queries to reduce database network traffic. After completing this course, you’ll have a solid foundation on using LINQ to query database and Entity Framework data. 6 | 7 | ## Instructions 8 | This repository has one MAIN branch for the course. 9 | 10 | ## Installing 11 | 1. To use these exercise files, you must have the following installed: 12 | - [Visual Studio](https://visualstudio.microsoft.com/) 13 | - [LINQPad](https://www.linqpad.net/) 14 | 2. Clone this repository into your local machine using the Visual Studio, or OS command line tool (Powershell, Windows Terminal) or MAC equivalent . 15 | 3. See the intro chapter for information about this course Git branches. 16 | 17 | ### Instructor 18 | 19 | **Walt Ritscher ** 20 | 21 | _Walt Ritscher is a programmer, UI designer, and staff author at LinkedIn Learning._ 22 | 23 | Check out some of my other courses on [LinkedIn Learning](https://www.linkedin.com/learning/instructors/walt-ritscher?u=104). 24 | 25 | [lil-course-url]: https://www.linkedin.com/learning/dot-net-essentials-linq-for-databases 26 | [lil-thumbnail-url]: https://cdn.lynda.com/course/2858036/2858036-1610558892801-16x9.jpg 27 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Order.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Order 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Order() 19 | { 20 | this.Order_Details = new HashSet(); 21 | } 22 | 23 | public int OrderID { get; set; } 24 | public string CustomerID { get; set; } 25 | public Nullable EmployeeID { get; set; } 26 | public Nullable OrderDate { get; set; } 27 | public Nullable RequiredDate { get; set; } 28 | public Nullable ShippedDate { get; set; } 29 | public Nullable ShipVia { get; set; } 30 | public Nullable Freight { get; set; } 31 | public string ShipName { get; set; } 32 | public string ShipAddress { get; set; } 33 | public string ShipCity { get; set; } 34 | public string ShipRegion { get; set; } 35 | public string ShipPostalCode { get; set; } 36 | public string ShipCountry { get; set; } 37 | 38 | public virtual Customer Customer { get; set; } 39 | public virtual Employee Employee { get; set; } 40 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 41 | public virtual ICollection Order_Details { get; set; } 42 | public virtual Shipper Shipper { get; set; } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/Employee.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated from a template. 4 | // 5 | // Manual changes to this file may cause unexpected behavior in your application. 6 | // Manual changes to this file will be overwritten if the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ConsoleForEF 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Employee 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Employee() 19 | { 20 | this.Employees1 = new HashSet(); 21 | this.Orders = new HashSet(); 22 | this.Territories = new HashSet(); 23 | } 24 | 25 | public int EmployeeID { get; set; } 26 | public string LastName { get; set; } 27 | public string FirstName { get; set; } 28 | public string Title { get; set; } 29 | public string TitleOfCourtesy { get; set; } 30 | public Nullable BirthDate { get; set; } 31 | public Nullable HireDate { get; set; } 32 | public string Address { get; set; } 33 | public string City { get; set; } 34 | public string Region { get; set; } 35 | public string PostalCode { get; set; } 36 | public string Country { get; set; } 37 | public string HomePhone { get; set; } 38 | public string Extension { get; set; } 39 | public byte[] Photo { get; set; } 40 | public string Notes { get; set; } 41 | public Nullable ReportsTo { get; set; } 42 | public string PhotoPath { get; set; } 43 | 44 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 45 | public virtual ICollection Employees1 { get; set; } 46 | public virtual Employee Employee1 { get; set; } 47 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 48 | public virtual ICollection Orders { get; set; } 49 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 50 | public virtual ICollection Territories { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/NorthwindModel.edmx.diagram: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | LinkedIn Learning Exercise Files License Agreement 2 | ================================================== 3 | 4 | This License Agreement (the "Agreement") is a binding legal agreement 5 | between you (as an individual or entity, as applicable) and LinkedIn 6 | Corporation (“LinkedIn”). By downloading or using the LinkedIn Learning 7 | exercise files in this repository (“Licensed Materials”), you agree to 8 | be bound by the terms of this Agreement. If you do not agree to these 9 | terms, do not download or use the Licensed Materials. 10 | 11 | 1. License. 12 | - a. Subject to the terms of this Agreement, LinkedIn hereby grants LinkedIn 13 | members during their LinkedIn Learning subscription a non-exclusive, 14 | non-transferable copyright license, for internal use only, to 1) make a 15 | reasonable number of copies of the Licensed Materials, and 2) make 16 | derivative works of the Licensed Materials for the sole purpose of 17 | practicing skills taught in LinkedIn Learning courses. 18 | - b. Distribution. Unless otherwise noted in the Licensed Materials, subject 19 | to the terms of this Agreement, LinkedIn hereby grants LinkedIn members 20 | with a LinkedIn Learning subscription a non-exclusive, non-transferable 21 | copyright license to distribute the Licensed Materials, except the 22 | Licensed Materials may not be included in any product or service (or 23 | otherwise used) to instruct or educate others. 24 | 25 | 2. Restrictions and Intellectual Property. 26 | - a. You may not to use, modify, copy, make derivative works of, publish, 27 | distribute, rent, lease, sell, sublicense, assign or otherwise transfer the 28 | Licensed Materials, except as expressly set forth above in Section 1. 29 | - b. Linkedin (and its licensors) retains its intellectual property rights 30 | in the Licensed Materials. Except as expressly set forth in Section 1, 31 | LinkedIn grants no licenses. 32 | - c. You indemnify LinkedIn and its licensors and affiliates for i) any 33 | alleged infringement or misappropriation of any intellectual property rights 34 | of any third party based on modifications you make to the Licensed Materials, 35 | ii) any claims arising from your use or distribution of all or part of the 36 | Licensed Materials and iii) a breach of this Agreement. You will defend, hold 37 | harmless, and indemnify LinkedIn and its affiliates (and our and their 38 | respective employees, shareholders, and directors) from any claim or action 39 | brought by a third party, including all damages, liabilities, costs and 40 | expenses, including reasonable attorneys’ fees, to the extent resulting from, 41 | alleged to have resulted from, or in connection with: (a) your breach of your 42 | obligations herein; or (b) your use or distribution of any Licensed Materials. 43 | 44 | 3. Open source. This code may include open source software, which may be 45 | subject to other license terms as provided in the files. 46 | 47 | 4. Warranty Disclaimer. LINKEDIN PROVIDES THE LICENSED MATERIALS ON AN “AS IS” 48 | AND “AS AVAILABLE” BASIS. LINKEDIN MAKES NO REPRESENTATION OR WARRANTY, 49 | WHETHER EXPRESS OR IMPLIED, ABOUT THE LICENSED MATERIALS, INCLUDING ANY 50 | REPRESENTATION THAT THE LICENSED MATERIALS WILL BE FREE OF ERRORS, BUGS OR 51 | INTERRUPTIONS, OR THAT THE LICENSED MATERIALS ARE ACCURATE, COMPLETE OR 52 | OTHERWISE VALID. TO THE FULLEST EXTENT PERMITTED BY LAW, LINKEDIN AND ITS 53 | AFFILIATES DISCLAIM ANY IMPLIED OR STATUTORY WARRANTY OR CONDITION, INCLUDING 54 | ANY IMPLIED WARRANTY OR CONDITION OF MERCHANTABILITY OR FITNESS FOR A 55 | PARTICULAR PURPOSE, AVAILABILITY, SECURITY, TITLE AND/OR NON-INFRINGEMENT. 56 | YOUR USE OF THE LICENSED MATERIALS IS AT YOUR OWN DISCRETION AND RISK, AND 57 | YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGE THAT RESULTS FROM USE OF THE 58 | LICENSED MATERIALS TO YOUR COMPUTER SYSTEM OR LOSS OF DATA. NO ADVICE OR 59 | INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU FROM US OR THROUGH OR 60 | FROM THE LICENSED MATERIALS WILL CREATE ANY WARRANTY OR CONDITION NOT 61 | EXPRESSLY STATED IN THESE TERMS. 62 | 63 | 5. Limitation of Liability. LINKEDIN SHALL NOT BE LIABLE FOR ANY INDIRECT, 64 | INCIDENTAL, SPECIAL, PUNITIVE, CONSEQUENTIAL OR EXEMPLARY DAMAGES, INCLUDING 65 | BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, DATA OR OTHER 66 | INTANGIBLE LOSSES . IN NO EVENT WILL LINKEDIN'S AGGREGATE LIABILITY TO YOU 67 | EXCEED $100. THIS LIMITATION OF LIABILITY SHALL: 68 | - i. APPLY REGARDLESS OF WHETHER (A) YOU BASE YOUR CLAIM ON CONTRACT, TORT, 69 | STATUTE, OR ANY OTHER LEGAL THEORY, (B) WE KNEW OR SHOULD HAVE KNOWN ABOUT 70 | THE POSSIBILITY OF SUCH DAMAGES, OR (C) THE LIMITED REMEDIES PROVIDED IN THIS 71 | SECTION FAIL OF THEIR ESSENTIAL PURPOSE; AND 72 | - ii. NOT APPLY TO ANY DAMAGE THAT LINKEDIN MAY CAUSE YOU INTENTIONALLY OR 73 | KNOWINGLY IN VIOLATION OF THESE TERMS OR APPLICABLE LAW, OR AS OTHERWISE 74 | MANDATED BY APPLICABLE LAW THAT CANNOT BE DISCLAIMED IN THESE TERMS. 75 | 76 | 6. Termination. This Agreement automatically terminates upon your breach of 77 | this Agreement or termination of your LinkedIn Learning subscription. On 78 | termination, all licenses granted under this Agreement will terminate 79 | immediately and you will delete the Licensed Materials. Sections 2-7 of this 80 | Agreement survive any termination of this Agreement. LinkedIn may discontinue 81 | the availability of some or all of the Licensed Materials at any time for any 82 | reason. 83 | 84 | 7. Miscellaneous. This Agreement will be governed by and construed in 85 | accordance with the laws of the State of California without regard to conflict 86 | of laws principles. The exclusive forum for any disputes arising out of or 87 | relating to this Agreement shall be an appropriate federal or state court 88 | sitting in the County of Santa Clara, State of California. If LinkedIn does 89 | not act to enforce a breach of this Agreement, that does not mean that 90 | LinkedIn has waived its right to enforce this Agreement. The Agreement does 91 | not create a partnership, agency relationship, or joint venture between the 92 | parties. Neither party has the power or authority to bind the other or to 93 | create any obligation or responsibility on behalf of the other. You may not, 94 | without LinkedIn’s prior written consent, assign or delegate any rights or 95 | obligations under these terms, including in connection with a change of 96 | control. Any purported assignment and delegation shall be ineffective. The 97 | Agreement shall bind and inure to the benefit of the parties, their respective 98 | successors and permitted assigns. If any provision of the Agreement is 99 | unenforceable, that provision will be modified to render it enforceable to the 100 | extent possible to give effect to the parties’ intentions and the remaining 101 | provisions will not be affected. This Agreement is the only agreement between 102 | you and LinkedIn regarding the Licensed Materials, and supersedes all prior 103 | agreements relating to the Licensed Materials. 104 | 105 | Last Updated: March 2019 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb 341 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ToursModel.edmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ConsoleForEF.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {576E8704-2FFB-4211-9AE9-2CE09902ED87} 8 | Exe 9 | ConsoleForEF 10 | ConsoleForEF 11 | v4.7 12 | 512 13 | true 14 | true 15 | false 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | true 30 | 31 | 32 | AnyCPU 33 | true 34 | full 35 | false 36 | bin\Debug\ 37 | DEBUG;TRACE 38 | prompt 39 | 4 40 | 41 | 42 | AnyCPU 43 | pdbonly 44 | true 45 | bin\Release\ 46 | TRACE 47 | prompt 48 | 4 49 | 50 | 51 | 52 | ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll 53 | 54 | 55 | ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | NorthwindModel.tt 72 | 73 | 74 | NorthwindModel.tt 75 | 76 | 77 | NorthwindModel.tt 78 | 79 | 80 | NorthwindModel.tt 81 | 82 | 83 | True 84 | True 85 | NorthwindModel.Context.tt 86 | 87 | 88 | True 89 | True 90 | NorthwindModel.tt 91 | 92 | 93 | True 94 | True 95 | NorthwindModel.edmx 96 | 97 | 98 | NorthwindModel.tt 99 | 100 | 101 | NorthwindModel.tt 102 | 103 | 104 | NorthwindModel.tt 105 | 106 | 107 | 108 | 109 | NorthwindModel.tt 110 | 111 | 112 | NorthwindModel.tt 113 | 114 | 115 | NorthwindModel.tt 116 | 117 | 118 | NorthwindModel.tt 119 | 120 | 121 | ToursModel.tt 122 | 123 | 124 | ToursModel.tt 125 | 126 | 127 | True 128 | True 129 | ToursModel.Context.tt 130 | 131 | 132 | True 133 | True 134 | ToursModel.tt 135 | 136 | 137 | True 138 | True 139 | ToursModel.edmx 140 | 141 | 142 | ToursModel.tt 143 | 144 | 145 | 146 | 147 | 148 | EntityModelCodeGenerator 149 | ToursModel.Designer.cs 150 | 151 | 152 | 153 | 154 | EntityModelCodeGenerator 155 | NorthwindModel.Designer.cs 156 | 157 | 158 | NorthwindModel.edmx 159 | 160 | 161 | 162 | ToursModel.edmx 163 | 164 | 165 | 166 | 167 | TextTemplatingFileGenerator 168 | NorthwindModel.edmx 169 | NorthwindModel.Context.cs 170 | 171 | 172 | TextTemplatingFileGenerator 173 | NorthwindModel.edmx 174 | NorthwindModel.cs 175 | 176 | 177 | Always 178 | 179 | 180 | Always 181 | NorthwindV13.MDF 182 | 183 | 184 | Always 185 | 186 | 187 | TextTemplatingFileGenerator 188 | ToursModel.Context.cs 189 | ToursModel.edmx 190 | 191 | 192 | TextTemplatingFileGenerator 193 | ToursModel.edmx 194 | ToursModel.cs 195 | 196 | 197 | Always 198 | Tours.mdf 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | False 207 | Microsoft .NET Framework 4.7 %28x86 and x64%29 208 | true 209 | 210 | 211 | False 212 | .NET Framework 3.5 SP1 213 | false 214 | 215 | 216 | 217 | -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ToursModel.Context.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" debug="false" hostspecific="true"#> 2 | <#@ include file="EF6.Utility.CS.ttinclude"#><#@ 3 | output extension=".cs"#><# 4 | 5 | const string inputFile = @"ToursModel.edmx"; 6 | var textTransform = DynamicTextTransformation.Create(this); 7 | var code = new CodeGenerationTools(this); 8 | var ef = new MetadataTools(this); 9 | var typeMapper = new TypeMapper(code, ef, textTransform.Errors); 10 | var loader = new EdmMetadataLoader(textTransform.Host, textTransform.Errors); 11 | var itemCollection = loader.CreateEdmItemCollection(inputFile); 12 | var modelNamespace = loader.GetModelNamespace(inputFile); 13 | var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef); 14 | 15 | var container = itemCollection.OfType().FirstOrDefault(); 16 | if (container == null) 17 | { 18 | return string.Empty; 19 | } 20 | #> 21 | //------------------------------------------------------------------------------ 22 | // 23 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#> 24 | // 25 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#> 26 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#> 27 | // 28 | //------------------------------------------------------------------------------ 29 | 30 | <# 31 | 32 | var codeNamespace = code.VsNamespaceSuggestion(); 33 | if (!String.IsNullOrEmpty(codeNamespace)) 34 | { 35 | #> 36 | namespace <#=code.EscapeNamespace(codeNamespace)#> 37 | { 38 | <# 39 | PushIndent(" "); 40 | } 41 | 42 | #> 43 | using System; 44 | using System.Data.Entity; 45 | using System.Data.Entity.Infrastructure; 46 | <# 47 | if (container.FunctionImports.Any()) 48 | { 49 | #> 50 | using System.Data.Entity.Core.Objects; 51 | using System.Linq; 52 | <# 53 | } 54 | #> 55 | 56 | <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext 57 | { 58 | public <#=code.Escape(container)#>() 59 | : base("name=<#=container.Name#>") 60 | { 61 | <# 62 | if (!loader.IsLazyLoadingEnabled(container)) 63 | { 64 | #> 65 | this.Configuration.LazyLoadingEnabled = false; 66 | <# 67 | } 68 | 69 | foreach (var entitySet in container.BaseEntitySets.OfType()) 70 | { 71 | // Note: the DbSet members are defined below such that the getter and 72 | // setter always have the same accessibility as the DbSet definition 73 | if (Accessibility.ForReadOnlyProperty(entitySet) != "public") 74 | { 75 | #> 76 | <#=codeStringGenerator.DbSetInitializer(entitySet)#> 77 | <# 78 | } 79 | } 80 | #> 81 | } 82 | 83 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 84 | { 85 | throw new UnintentionalCodeFirstException(); 86 | } 87 | 88 | <# 89 | foreach (var entitySet in container.BaseEntitySets.OfType()) 90 | { 91 | #> 92 | <#=codeStringGenerator.DbSet(entitySet)#> 93 | <# 94 | } 95 | 96 | foreach (var edmFunction in container.FunctionImports) 97 | { 98 | WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false); 99 | } 100 | #> 101 | } 102 | <# 103 | 104 | if (!String.IsNullOrEmpty(codeNamespace)) 105 | { 106 | PopIndent(); 107 | #> 108 | } 109 | <# 110 | } 111 | #> 112 | <#+ 113 | 114 | private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 115 | { 116 | if (typeMapper.IsComposable(edmFunction)) 117 | { 118 | #> 119 | 120 | [DbFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")] 121 | <#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#> 122 | { 123 | <#+ 124 | codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter); 125 | #> 126 | <#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#> 127 | } 128 | <#+ 129 | } 130 | else 131 | { 132 | #> 133 | 134 | <#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#> 135 | { 136 | <#+ 137 | codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter); 138 | #> 139 | <#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#> 140 | } 141 | <#+ 142 | if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption)) 143 | { 144 | WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true); 145 | } 146 | } 147 | } 148 | 149 | public void WriteFunctionParameter(string name, string isNotNull, string notNullInit, string nullInit) 150 | { 151 | #> 152 | var <#=name#> = <#=isNotNull#> ? 153 | <#=notNullInit#> : 154 | <#=nullInit#>; 155 | 156 | <#+ 157 | } 158 | 159 | public const string TemplateId = "CSharp_DbContext_Context_EF6"; 160 | 161 | public class CodeStringGenerator 162 | { 163 | private readonly CodeGenerationTools _code; 164 | private readonly TypeMapper _typeMapper; 165 | private readonly MetadataTools _ef; 166 | 167 | public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef) 168 | { 169 | ArgumentNotNull(code, "code"); 170 | ArgumentNotNull(typeMapper, "typeMapper"); 171 | ArgumentNotNull(ef, "ef"); 172 | 173 | _code = code; 174 | _typeMapper = typeMapper; 175 | _ef = ef; 176 | } 177 | 178 | public string Property(EdmProperty edmProperty) 179 | { 180 | return string.Format( 181 | CultureInfo.InvariantCulture, 182 | "{0} {1} {2} {{ {3}get; {4}set; }}", 183 | Accessibility.ForProperty(edmProperty), 184 | _typeMapper.GetTypeName(edmProperty.TypeUsage), 185 | _code.Escape(edmProperty), 186 | _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 187 | _code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 188 | } 189 | 190 | public string NavigationProperty(NavigationProperty navProp) 191 | { 192 | var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType()); 193 | return string.Format( 194 | CultureInfo.InvariantCulture, 195 | "{0} {1} {2} {{ {3}get; {4}set; }}", 196 | AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)), 197 | navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, 198 | _code.Escape(navProp), 199 | _code.SpaceAfter(Accessibility.ForGetter(navProp)), 200 | _code.SpaceAfter(Accessibility.ForSetter(navProp))); 201 | } 202 | 203 | public string AccessibilityAndVirtual(string accessibility) 204 | { 205 | return accessibility + (accessibility != "private" ? " virtual" : ""); 206 | } 207 | 208 | public string EntityClassOpening(EntityType entity) 209 | { 210 | return string.Format( 211 | CultureInfo.InvariantCulture, 212 | "{0} {1}partial class {2}{3}", 213 | Accessibility.ForType(entity), 214 | _code.SpaceAfter(_code.AbstractOption(entity)), 215 | _code.Escape(entity), 216 | _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType))); 217 | } 218 | 219 | public string EnumOpening(SimpleType enumType) 220 | { 221 | return string.Format( 222 | CultureInfo.InvariantCulture, 223 | "{0} enum {1} : {2}", 224 | Accessibility.ForType(enumType), 225 | _code.Escape(enumType), 226 | _code.Escape(_typeMapper.UnderlyingClrType(enumType))); 227 | } 228 | 229 | public void WriteFunctionParameters(EdmFunction edmFunction, Action writeParameter) 230 | { 231 | var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); 232 | foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable)) 233 | { 234 | var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"; 235 | var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")"; 236 | var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))"; 237 | writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit); 238 | } 239 | } 240 | 241 | public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace) 242 | { 243 | var parameters = _typeMapper.GetParameters(edmFunction); 244 | 245 | return string.Format( 246 | CultureInfo.InvariantCulture, 247 | "{0} IQueryable<{1}> {2}({3})", 248 | AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), 249 | _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), 250 | _code.Escape(edmFunction), 251 | string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray())); 252 | } 253 | 254 | public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace) 255 | { 256 | var parameters = _typeMapper.GetParameters(edmFunction); 257 | 258 | return string.Format( 259 | CultureInfo.InvariantCulture, 260 | "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});", 261 | _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), 262 | edmFunction.NamespaceName, 263 | edmFunction.Name, 264 | string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()), 265 | _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))); 266 | } 267 | 268 | public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 269 | { 270 | var parameters = _typeMapper.GetParameters(edmFunction); 271 | var returnType = _typeMapper.GetReturnType(edmFunction); 272 | 273 | var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()); 274 | if (includeMergeOption) 275 | { 276 | paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption"; 277 | } 278 | 279 | return string.Format( 280 | CultureInfo.InvariantCulture, 281 | "{0} {1} {2}({3})", 282 | AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), 283 | returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", 284 | _code.Escape(edmFunction), 285 | paramList); 286 | } 287 | 288 | public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 289 | { 290 | var parameters = _typeMapper.GetParameters(edmFunction); 291 | var returnType = _typeMapper.GetReturnType(edmFunction); 292 | 293 | var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())); 294 | if (includeMergeOption) 295 | { 296 | callParams = ", mergeOption" + callParams; 297 | } 298 | 299 | return string.Format( 300 | CultureInfo.InvariantCulture, 301 | "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});", 302 | returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", 303 | edmFunction.Name, 304 | callParams); 305 | } 306 | 307 | public string DbSet(EntitySet entitySet) 308 | { 309 | return string.Format( 310 | CultureInfo.InvariantCulture, 311 | "{0} virtual DbSet<{1}> {2} {{ get; set; }}", 312 | Accessibility.ForReadOnlyProperty(entitySet), 313 | _typeMapper.GetTypeName(entitySet.ElementType), 314 | _code.Escape(entitySet)); 315 | } 316 | 317 | public string DbSetInitializer(EntitySet entitySet) 318 | { 319 | return string.Format( 320 | CultureInfo.InvariantCulture, 321 | "{0} = Set<{1}>();", 322 | _code.Escape(entitySet), 323 | _typeMapper.GetTypeName(entitySet.ElementType)); 324 | } 325 | 326 | public string UsingDirectives(bool inHeader, bool includeCollections = true) 327 | { 328 | return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion()) 329 | ? string.Format( 330 | CultureInfo.InvariantCulture, 331 | "{0}using System;{1}" + 332 | "{2}", 333 | inHeader ? Environment.NewLine : "", 334 | includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "", 335 | inHeader ? "" : Environment.NewLine) 336 | : ""; 337 | } 338 | } 339 | 340 | public class TypeMapper 341 | { 342 | private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName"; 343 | 344 | private readonly System.Collections.IList _errors; 345 | private readonly CodeGenerationTools _code; 346 | private readonly MetadataTools _ef; 347 | 348 | public static string FixNamespaces(string typeName) 349 | { 350 | return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial."); 351 | } 352 | 353 | public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors) 354 | { 355 | ArgumentNotNull(code, "code"); 356 | ArgumentNotNull(ef, "ef"); 357 | ArgumentNotNull(errors, "errors"); 358 | 359 | _code = code; 360 | _ef = ef; 361 | _errors = errors; 362 | } 363 | 364 | public string GetTypeName(TypeUsage typeUsage) 365 | { 366 | return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null); 367 | } 368 | 369 | public string GetTypeName(EdmType edmType) 370 | { 371 | return GetTypeName(edmType, isNullable: null, modelNamespace: null); 372 | } 373 | 374 | public string GetTypeName(TypeUsage typeUsage, string modelNamespace) 375 | { 376 | return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace); 377 | } 378 | 379 | public string GetTypeName(EdmType edmType, string modelNamespace) 380 | { 381 | return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace); 382 | } 383 | 384 | public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace) 385 | { 386 | if (edmType == null) 387 | { 388 | return null; 389 | } 390 | 391 | var collectionType = edmType as CollectionType; 392 | if (collectionType != null) 393 | { 394 | return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace)); 395 | } 396 | 397 | var typeName = _code.Escape(edmType.MetadataProperties 398 | .Where(p => p.Name == ExternalTypeNameAttributeName) 399 | .Select(p => (string)p.Value) 400 | .FirstOrDefault()) 401 | ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ? 402 | _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) : 403 | _code.Escape(edmType)); 404 | 405 | if (edmType is StructuralType) 406 | { 407 | return typeName; 408 | } 409 | 410 | if (edmType is SimpleType) 411 | { 412 | var clrType = UnderlyingClrType(edmType); 413 | if (!IsEnumType(edmType)) 414 | { 415 | typeName = _code.Escape(clrType); 416 | } 417 | 418 | typeName = FixNamespaces(typeName); 419 | 420 | return clrType.IsValueType && isNullable == true ? 421 | String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) : 422 | typeName; 423 | } 424 | 425 | throw new ArgumentException("edmType"); 426 | } 427 | 428 | public Type UnderlyingClrType(EdmType edmType) 429 | { 430 | ArgumentNotNull(edmType, "edmType"); 431 | 432 | var primitiveType = edmType as PrimitiveType; 433 | if (primitiveType != null) 434 | { 435 | return primitiveType.ClrEquivalentType; 436 | } 437 | 438 | if (IsEnumType(edmType)) 439 | { 440 | return GetEnumUnderlyingType(edmType).ClrEquivalentType; 441 | } 442 | 443 | return typeof(object); 444 | } 445 | 446 | public object GetEnumMemberValue(MetadataItem enumMember) 447 | { 448 | ArgumentNotNull(enumMember, "enumMember"); 449 | 450 | var valueProperty = enumMember.GetType().GetProperty("Value"); 451 | return valueProperty == null ? null : valueProperty.GetValue(enumMember, null); 452 | } 453 | 454 | public string GetEnumMemberName(MetadataItem enumMember) 455 | { 456 | ArgumentNotNull(enumMember, "enumMember"); 457 | 458 | var nameProperty = enumMember.GetType().GetProperty("Name"); 459 | return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null); 460 | } 461 | 462 | public System.Collections.IEnumerable GetEnumMembers(EdmType enumType) 463 | { 464 | ArgumentNotNull(enumType, "enumType"); 465 | 466 | var membersProperty = enumType.GetType().GetProperty("Members"); 467 | return membersProperty != null 468 | ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null) 469 | : Enumerable.Empty(); 470 | } 471 | 472 | public bool EnumIsFlags(EdmType enumType) 473 | { 474 | ArgumentNotNull(enumType, "enumType"); 475 | 476 | var isFlagsProperty = enumType.GetType().GetProperty("IsFlags"); 477 | return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null); 478 | } 479 | 480 | public bool IsEnumType(GlobalItem edmType) 481 | { 482 | ArgumentNotNull(edmType, "edmType"); 483 | 484 | return edmType.GetType().Name == "EnumType"; 485 | } 486 | 487 | public PrimitiveType GetEnumUnderlyingType(EdmType enumType) 488 | { 489 | ArgumentNotNull(enumType, "enumType"); 490 | 491 | return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null); 492 | } 493 | 494 | public string CreateLiteral(object value) 495 | { 496 | if (value == null || value.GetType() != typeof(TimeSpan)) 497 | { 498 | return _code.CreateLiteral(value); 499 | } 500 | 501 | return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks); 502 | } 503 | 504 | public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable types, string sourceFile) 505 | { 506 | ArgumentNotNull(types, "types"); 507 | ArgumentNotNull(sourceFile, "sourceFile"); 508 | 509 | var hash = new HashSet(StringComparer.InvariantCultureIgnoreCase); 510 | if (types.Any(item => !hash.Add(item))) 511 | { 512 | _errors.Add( 513 | new CompilerError(sourceFile, -1, -1, "6023", 514 | String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict")))); 515 | return false; 516 | } 517 | return true; 518 | } 519 | 520 | public IEnumerable GetEnumItemsToGenerate(IEnumerable itemCollection) 521 | { 522 | return GetItemsToGenerate(itemCollection) 523 | .Where(e => IsEnumType(e)); 524 | } 525 | 526 | public IEnumerable GetItemsToGenerate(IEnumerable itemCollection) where T: EdmType 527 | { 528 | return itemCollection 529 | .OfType() 530 | .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName)) 531 | .OrderBy(i => i.Name); 532 | } 533 | 534 | public IEnumerable GetAllGlobalItems(IEnumerable itemCollection) 535 | { 536 | return itemCollection 537 | .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i)) 538 | .Select(g => GetGlobalItemName(g)); 539 | } 540 | 541 | public string GetGlobalItemName(GlobalItem item) 542 | { 543 | if (item is EdmType) 544 | { 545 | return ((EdmType)item).Name; 546 | } 547 | else 548 | { 549 | return ((EntityContainer)item).Name; 550 | } 551 | } 552 | 553 | public IEnumerable GetSimpleProperties(EntityType type) 554 | { 555 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); 556 | } 557 | 558 | public IEnumerable GetSimpleProperties(ComplexType type) 559 | { 560 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); 561 | } 562 | 563 | public IEnumerable GetComplexProperties(EntityType type) 564 | { 565 | return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); 566 | } 567 | 568 | public IEnumerable GetComplexProperties(ComplexType type) 569 | { 570 | return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); 571 | } 572 | 573 | public IEnumerable GetPropertiesWithDefaultValues(EntityType type) 574 | { 575 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); 576 | } 577 | 578 | public IEnumerable GetPropertiesWithDefaultValues(ComplexType type) 579 | { 580 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); 581 | } 582 | 583 | public IEnumerable GetNavigationProperties(EntityType type) 584 | { 585 | return type.NavigationProperties.Where(np => np.DeclaringType == type); 586 | } 587 | 588 | public IEnumerable GetCollectionNavigationProperties(EntityType type) 589 | { 590 | return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many); 591 | } 592 | 593 | public FunctionParameter GetReturnParameter(EdmFunction edmFunction) 594 | { 595 | ArgumentNotNull(edmFunction, "edmFunction"); 596 | 597 | var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters"); 598 | return returnParamsProperty == null 599 | ? edmFunction.ReturnParameter 600 | : ((IEnumerable)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault(); 601 | } 602 | 603 | public bool IsComposable(EdmFunction edmFunction) 604 | { 605 | ArgumentNotNull(edmFunction, "edmFunction"); 606 | 607 | var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute"); 608 | return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null); 609 | } 610 | 611 | public IEnumerable GetParameters(EdmFunction edmFunction) 612 | { 613 | return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); 614 | } 615 | 616 | public TypeUsage GetReturnType(EdmFunction edmFunction) 617 | { 618 | var returnParam = GetReturnParameter(edmFunction); 619 | return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage); 620 | } 621 | 622 | public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption) 623 | { 624 | var returnType = GetReturnType(edmFunction); 625 | return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType; 626 | } 627 | } 628 | 629 | public static void ArgumentNotNull(T arg, string name) where T : class 630 | { 631 | if (arg == null) 632 | { 633 | throw new ArgumentNullException(name); 634 | } 635 | } 636 | #> -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/NorthwindModel.Context.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" debug="false" hostspecific="true"#> 2 | <#@ include file="EF6.Utility.CS.ttinclude"#><#@ 3 | output extension=".cs"#><# 4 | 5 | const string inputFile = @"NorthwindModel.edmx"; 6 | var textTransform = DynamicTextTransformation.Create(this); 7 | var code = new CodeGenerationTools(this); 8 | var ef = new MetadataTools(this); 9 | var typeMapper = new TypeMapper(code, ef, textTransform.Errors); 10 | var loader = new EdmMetadataLoader(textTransform.Host, textTransform.Errors); 11 | var itemCollection = loader.CreateEdmItemCollection(inputFile); 12 | var modelNamespace = loader.GetModelNamespace(inputFile); 13 | var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef); 14 | 15 | var container = itemCollection.OfType().FirstOrDefault(); 16 | if (container == null) 17 | { 18 | return string.Empty; 19 | } 20 | #> 21 | //------------------------------------------------------------------------------ 22 | // 23 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#> 24 | // 25 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#> 26 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#> 27 | // 28 | //------------------------------------------------------------------------------ 29 | 30 | <# 31 | 32 | var codeNamespace = code.VsNamespaceSuggestion(); 33 | if (!String.IsNullOrEmpty(codeNamespace)) 34 | { 35 | #> 36 | namespace <#=code.EscapeNamespace(codeNamespace)#> 37 | { 38 | <# 39 | PushIndent(" "); 40 | } 41 | 42 | #> 43 | using System; 44 | using System.Data.Entity; 45 | using System.Data.Entity.Infrastructure; 46 | <# 47 | if (container.FunctionImports.Any()) 48 | { 49 | #> 50 | using System.Data.Entity.Core.Objects; 51 | using System.Linq; 52 | <# 53 | } 54 | #> 55 | 56 | <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext 57 | { 58 | public <#=code.Escape(container)#>() 59 | : base("name=<#=container.Name#>") 60 | { 61 | <# 62 | if (!loader.IsLazyLoadingEnabled(container)) 63 | { 64 | #> 65 | this.Configuration.LazyLoadingEnabled = false; 66 | <# 67 | } 68 | 69 | foreach (var entitySet in container.BaseEntitySets.OfType()) 70 | { 71 | // Note: the DbSet members are defined below such that the getter and 72 | // setter always have the same accessibility as the DbSet definition 73 | if (Accessibility.ForReadOnlyProperty(entitySet) != "public") 74 | { 75 | #> 76 | <#=codeStringGenerator.DbSetInitializer(entitySet)#> 77 | <# 78 | } 79 | } 80 | #> 81 | } 82 | 83 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 84 | { 85 | throw new UnintentionalCodeFirstException(); 86 | } 87 | 88 | <# 89 | foreach (var entitySet in container.BaseEntitySets.OfType()) 90 | { 91 | #> 92 | <#=codeStringGenerator.DbSet(entitySet)#> 93 | <# 94 | } 95 | 96 | foreach (var edmFunction in container.FunctionImports) 97 | { 98 | WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false); 99 | } 100 | #> 101 | } 102 | <# 103 | 104 | if (!String.IsNullOrEmpty(codeNamespace)) 105 | { 106 | PopIndent(); 107 | #> 108 | } 109 | <# 110 | } 111 | #> 112 | <#+ 113 | 114 | private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 115 | { 116 | if (typeMapper.IsComposable(edmFunction)) 117 | { 118 | #> 119 | 120 | [DbFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")] 121 | <#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#> 122 | { 123 | <#+ 124 | codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter); 125 | #> 126 | <#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#> 127 | } 128 | <#+ 129 | } 130 | else 131 | { 132 | #> 133 | 134 | <#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#> 135 | { 136 | <#+ 137 | codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter); 138 | #> 139 | <#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#> 140 | } 141 | <#+ 142 | if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption)) 143 | { 144 | WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true); 145 | } 146 | } 147 | } 148 | 149 | public void WriteFunctionParameter(string name, string isNotNull, string notNullInit, string nullInit) 150 | { 151 | #> 152 | var <#=name#> = <#=isNotNull#> ? 153 | <#=notNullInit#> : 154 | <#=nullInit#>; 155 | 156 | <#+ 157 | } 158 | 159 | public const string TemplateId = "CSharp_DbContext_Context_EF6"; 160 | 161 | public class CodeStringGenerator 162 | { 163 | private readonly CodeGenerationTools _code; 164 | private readonly TypeMapper _typeMapper; 165 | private readonly MetadataTools _ef; 166 | 167 | public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef) 168 | { 169 | ArgumentNotNull(code, "code"); 170 | ArgumentNotNull(typeMapper, "typeMapper"); 171 | ArgumentNotNull(ef, "ef"); 172 | 173 | _code = code; 174 | _typeMapper = typeMapper; 175 | _ef = ef; 176 | } 177 | 178 | public string Property(EdmProperty edmProperty) 179 | { 180 | return string.Format( 181 | CultureInfo.InvariantCulture, 182 | "{0} {1} {2} {{ {3}get; {4}set; }}", 183 | Accessibility.ForProperty(edmProperty), 184 | _typeMapper.GetTypeName(edmProperty.TypeUsage), 185 | _code.Escape(edmProperty), 186 | _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 187 | _code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 188 | } 189 | 190 | public string NavigationProperty(NavigationProperty navProp) 191 | { 192 | var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType()); 193 | return string.Format( 194 | CultureInfo.InvariantCulture, 195 | "{0} {1} {2} {{ {3}get; {4}set; }}", 196 | AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)), 197 | navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, 198 | _code.Escape(navProp), 199 | _code.SpaceAfter(Accessibility.ForGetter(navProp)), 200 | _code.SpaceAfter(Accessibility.ForSetter(navProp))); 201 | } 202 | 203 | public string AccessibilityAndVirtual(string accessibility) 204 | { 205 | return accessibility + (accessibility != "private" ? " virtual" : ""); 206 | } 207 | 208 | public string EntityClassOpening(EntityType entity) 209 | { 210 | return string.Format( 211 | CultureInfo.InvariantCulture, 212 | "{0} {1}partial class {2}{3}", 213 | Accessibility.ForType(entity), 214 | _code.SpaceAfter(_code.AbstractOption(entity)), 215 | _code.Escape(entity), 216 | _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType))); 217 | } 218 | 219 | public string EnumOpening(SimpleType enumType) 220 | { 221 | return string.Format( 222 | CultureInfo.InvariantCulture, 223 | "{0} enum {1} : {2}", 224 | Accessibility.ForType(enumType), 225 | _code.Escape(enumType), 226 | _code.Escape(_typeMapper.UnderlyingClrType(enumType))); 227 | } 228 | 229 | public void WriteFunctionParameters(EdmFunction edmFunction, Action writeParameter) 230 | { 231 | var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); 232 | foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable)) 233 | { 234 | var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"; 235 | var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")"; 236 | var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))"; 237 | writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit); 238 | } 239 | } 240 | 241 | public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace) 242 | { 243 | var parameters = _typeMapper.GetParameters(edmFunction); 244 | 245 | return string.Format( 246 | CultureInfo.InvariantCulture, 247 | "{0} IQueryable<{1}> {2}({3})", 248 | AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), 249 | _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), 250 | _code.Escape(edmFunction), 251 | string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray())); 252 | } 253 | 254 | public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace) 255 | { 256 | var parameters = _typeMapper.GetParameters(edmFunction); 257 | 258 | return string.Format( 259 | CultureInfo.InvariantCulture, 260 | "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});", 261 | _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), 262 | edmFunction.NamespaceName, 263 | edmFunction.Name, 264 | string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()), 265 | _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))); 266 | } 267 | 268 | public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 269 | { 270 | var parameters = _typeMapper.GetParameters(edmFunction); 271 | var returnType = _typeMapper.GetReturnType(edmFunction); 272 | 273 | var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()); 274 | if (includeMergeOption) 275 | { 276 | paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption"; 277 | } 278 | 279 | return string.Format( 280 | CultureInfo.InvariantCulture, 281 | "{0} {1} {2}({3})", 282 | AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), 283 | returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", 284 | _code.Escape(edmFunction), 285 | paramList); 286 | } 287 | 288 | public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 289 | { 290 | var parameters = _typeMapper.GetParameters(edmFunction); 291 | var returnType = _typeMapper.GetReturnType(edmFunction); 292 | 293 | var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())); 294 | if (includeMergeOption) 295 | { 296 | callParams = ", mergeOption" + callParams; 297 | } 298 | 299 | return string.Format( 300 | CultureInfo.InvariantCulture, 301 | "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});", 302 | returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", 303 | edmFunction.Name, 304 | callParams); 305 | } 306 | 307 | public string DbSet(EntitySet entitySet) 308 | { 309 | return string.Format( 310 | CultureInfo.InvariantCulture, 311 | "{0} virtual DbSet<{1}> {2} {{ get; set; }}", 312 | Accessibility.ForReadOnlyProperty(entitySet), 313 | _typeMapper.GetTypeName(entitySet.ElementType), 314 | _code.Escape(entitySet)); 315 | } 316 | 317 | public string DbSetInitializer(EntitySet entitySet) 318 | { 319 | return string.Format( 320 | CultureInfo.InvariantCulture, 321 | "{0} = Set<{1}>();", 322 | _code.Escape(entitySet), 323 | _typeMapper.GetTypeName(entitySet.ElementType)); 324 | } 325 | 326 | public string UsingDirectives(bool inHeader, bool includeCollections = true) 327 | { 328 | return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion()) 329 | ? string.Format( 330 | CultureInfo.InvariantCulture, 331 | "{0}using System;{1}" + 332 | "{2}", 333 | inHeader ? Environment.NewLine : "", 334 | includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "", 335 | inHeader ? "" : Environment.NewLine) 336 | : ""; 337 | } 338 | } 339 | 340 | public class TypeMapper 341 | { 342 | private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName"; 343 | 344 | private readonly System.Collections.IList _errors; 345 | private readonly CodeGenerationTools _code; 346 | private readonly MetadataTools _ef; 347 | 348 | public static string FixNamespaces(string typeName) 349 | { 350 | return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial."); 351 | } 352 | 353 | public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors) 354 | { 355 | ArgumentNotNull(code, "code"); 356 | ArgumentNotNull(ef, "ef"); 357 | ArgumentNotNull(errors, "errors"); 358 | 359 | _code = code; 360 | _ef = ef; 361 | _errors = errors; 362 | } 363 | 364 | public string GetTypeName(TypeUsage typeUsage) 365 | { 366 | return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null); 367 | } 368 | 369 | public string GetTypeName(EdmType edmType) 370 | { 371 | return GetTypeName(edmType, isNullable: null, modelNamespace: null); 372 | } 373 | 374 | public string GetTypeName(TypeUsage typeUsage, string modelNamespace) 375 | { 376 | return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace); 377 | } 378 | 379 | public string GetTypeName(EdmType edmType, string modelNamespace) 380 | { 381 | return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace); 382 | } 383 | 384 | public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace) 385 | { 386 | if (edmType == null) 387 | { 388 | return null; 389 | } 390 | 391 | var collectionType = edmType as CollectionType; 392 | if (collectionType != null) 393 | { 394 | return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace)); 395 | } 396 | 397 | var typeName = _code.Escape(edmType.MetadataProperties 398 | .Where(p => p.Name == ExternalTypeNameAttributeName) 399 | .Select(p => (string)p.Value) 400 | .FirstOrDefault()) 401 | ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ? 402 | _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) : 403 | _code.Escape(edmType)); 404 | 405 | if (edmType is StructuralType) 406 | { 407 | return typeName; 408 | } 409 | 410 | if (edmType is SimpleType) 411 | { 412 | var clrType = UnderlyingClrType(edmType); 413 | if (!IsEnumType(edmType)) 414 | { 415 | typeName = _code.Escape(clrType); 416 | } 417 | 418 | typeName = FixNamespaces(typeName); 419 | 420 | return clrType.IsValueType && isNullable == true ? 421 | String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) : 422 | typeName; 423 | } 424 | 425 | throw new ArgumentException("edmType"); 426 | } 427 | 428 | public Type UnderlyingClrType(EdmType edmType) 429 | { 430 | ArgumentNotNull(edmType, "edmType"); 431 | 432 | var primitiveType = edmType as PrimitiveType; 433 | if (primitiveType != null) 434 | { 435 | return primitiveType.ClrEquivalentType; 436 | } 437 | 438 | if (IsEnumType(edmType)) 439 | { 440 | return GetEnumUnderlyingType(edmType).ClrEquivalentType; 441 | } 442 | 443 | return typeof(object); 444 | } 445 | 446 | public object GetEnumMemberValue(MetadataItem enumMember) 447 | { 448 | ArgumentNotNull(enumMember, "enumMember"); 449 | 450 | var valueProperty = enumMember.GetType().GetProperty("Value"); 451 | return valueProperty == null ? null : valueProperty.GetValue(enumMember, null); 452 | } 453 | 454 | public string GetEnumMemberName(MetadataItem enumMember) 455 | { 456 | ArgumentNotNull(enumMember, "enumMember"); 457 | 458 | var nameProperty = enumMember.GetType().GetProperty("Name"); 459 | return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null); 460 | } 461 | 462 | public System.Collections.IEnumerable GetEnumMembers(EdmType enumType) 463 | { 464 | ArgumentNotNull(enumType, "enumType"); 465 | 466 | var membersProperty = enumType.GetType().GetProperty("Members"); 467 | return membersProperty != null 468 | ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null) 469 | : Enumerable.Empty(); 470 | } 471 | 472 | public bool EnumIsFlags(EdmType enumType) 473 | { 474 | ArgumentNotNull(enumType, "enumType"); 475 | 476 | var isFlagsProperty = enumType.GetType().GetProperty("IsFlags"); 477 | return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null); 478 | } 479 | 480 | public bool IsEnumType(GlobalItem edmType) 481 | { 482 | ArgumentNotNull(edmType, "edmType"); 483 | 484 | return edmType.GetType().Name == "EnumType"; 485 | } 486 | 487 | public PrimitiveType GetEnumUnderlyingType(EdmType enumType) 488 | { 489 | ArgumentNotNull(enumType, "enumType"); 490 | 491 | return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null); 492 | } 493 | 494 | public string CreateLiteral(object value) 495 | { 496 | if (value == null || value.GetType() != typeof(TimeSpan)) 497 | { 498 | return _code.CreateLiteral(value); 499 | } 500 | 501 | return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks); 502 | } 503 | 504 | public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable types, string sourceFile) 505 | { 506 | ArgumentNotNull(types, "types"); 507 | ArgumentNotNull(sourceFile, "sourceFile"); 508 | 509 | var hash = new HashSet(StringComparer.InvariantCultureIgnoreCase); 510 | if (types.Any(item => !hash.Add(item))) 511 | { 512 | _errors.Add( 513 | new CompilerError(sourceFile, -1, -1, "6023", 514 | String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict")))); 515 | return false; 516 | } 517 | return true; 518 | } 519 | 520 | public IEnumerable GetEnumItemsToGenerate(IEnumerable itemCollection) 521 | { 522 | return GetItemsToGenerate(itemCollection) 523 | .Where(e => IsEnumType(e)); 524 | } 525 | 526 | public IEnumerable GetItemsToGenerate(IEnumerable itemCollection) where T: EdmType 527 | { 528 | return itemCollection 529 | .OfType() 530 | .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName)) 531 | .OrderBy(i => i.Name); 532 | } 533 | 534 | public IEnumerable GetAllGlobalItems(IEnumerable itemCollection) 535 | { 536 | return itemCollection 537 | .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i)) 538 | .Select(g => GetGlobalItemName(g)); 539 | } 540 | 541 | public string GetGlobalItemName(GlobalItem item) 542 | { 543 | if (item is EdmType) 544 | { 545 | return ((EdmType)item).Name; 546 | } 547 | else 548 | { 549 | return ((EntityContainer)item).Name; 550 | } 551 | } 552 | 553 | public IEnumerable GetSimpleProperties(EntityType type) 554 | { 555 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); 556 | } 557 | 558 | public IEnumerable GetSimpleProperties(ComplexType type) 559 | { 560 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); 561 | } 562 | 563 | public IEnumerable GetComplexProperties(EntityType type) 564 | { 565 | return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); 566 | } 567 | 568 | public IEnumerable GetComplexProperties(ComplexType type) 569 | { 570 | return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); 571 | } 572 | 573 | public IEnumerable GetPropertiesWithDefaultValues(EntityType type) 574 | { 575 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); 576 | } 577 | 578 | public IEnumerable GetPropertiesWithDefaultValues(ComplexType type) 579 | { 580 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); 581 | } 582 | 583 | public IEnumerable GetNavigationProperties(EntityType type) 584 | { 585 | return type.NavigationProperties.Where(np => np.DeclaringType == type); 586 | } 587 | 588 | public IEnumerable GetCollectionNavigationProperties(EntityType type) 589 | { 590 | return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many); 591 | } 592 | 593 | public FunctionParameter GetReturnParameter(EdmFunction edmFunction) 594 | { 595 | ArgumentNotNull(edmFunction, "edmFunction"); 596 | 597 | var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters"); 598 | return returnParamsProperty == null 599 | ? edmFunction.ReturnParameter 600 | : ((IEnumerable)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault(); 601 | } 602 | 603 | public bool IsComposable(EdmFunction edmFunction) 604 | { 605 | ArgumentNotNull(edmFunction, "edmFunction"); 606 | 607 | var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute"); 608 | return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null); 609 | } 610 | 611 | public IEnumerable GetParameters(EdmFunction edmFunction) 612 | { 613 | return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); 614 | } 615 | 616 | public TypeUsage GetReturnType(EdmFunction edmFunction) 617 | { 618 | var returnParam = GetReturnParameter(edmFunction); 619 | return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage); 620 | } 621 | 622 | public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption) 623 | { 624 | var returnType = GetReturnType(edmFunction); 625 | return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType; 626 | } 627 | } 628 | 629 | public static void ArgumentNotNull(T arg, string name) where T : class 630 | { 631 | if (arg == null) 632 | { 633 | throw new ArgumentNullException(name); 634 | } 635 | } 636 | #> -------------------------------------------------------------------------------- /source/VisualStudio/ConsoleForEF/ToursModel.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" debug="false" hostspecific="true"#> 2 | <#@ include file="EF6.Utility.CS.ttinclude"#><#@ 3 | output extension=".cs"#><# 4 | 5 | const string inputFile = @"ToursModel.edmx"; 6 | var textTransform = DynamicTextTransformation.Create(this); 7 | var code = new CodeGenerationTools(this); 8 | var ef = new MetadataTools(this); 9 | var typeMapper = new TypeMapper(code, ef, textTransform.Errors); 10 | var fileManager = EntityFrameworkTemplateFileManager.Create(this); 11 | var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile); 12 | var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef); 13 | 14 | if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile)) 15 | { 16 | return string.Empty; 17 | } 18 | 19 | WriteHeader(codeStringGenerator, fileManager); 20 | 21 | foreach (var entity in typeMapper.GetItemsToGenerate(itemCollection)) 22 | { 23 | fileManager.StartNewFile(entity.Name + ".cs"); 24 | BeginNamespace(code); 25 | #> 26 | <#=codeStringGenerator.UsingDirectives(inHeader: false)#> 27 | <#=codeStringGenerator.EntityClassOpening(entity)#> 28 | { 29 | <# 30 | var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity); 31 | var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity); 32 | var complexProperties = typeMapper.GetComplexProperties(entity); 33 | 34 | if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any()) 35 | { 36 | #> 37 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 38 | public <#=code.Escape(entity)#>() 39 | { 40 | <# 41 | foreach (var edmProperty in propertiesWithDefaultValues) 42 | { 43 | #> 44 | this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>; 45 | <# 46 | } 47 | 48 | foreach (var navigationProperty in collectionNavigationProperties) 49 | { 50 | #> 51 | this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>(); 52 | <# 53 | } 54 | 55 | foreach (var complexProperty in complexProperties) 56 | { 57 | #> 58 | this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>(); 59 | <# 60 | } 61 | #> 62 | } 63 | 64 | <# 65 | } 66 | 67 | var simpleProperties = typeMapper.GetSimpleProperties(entity); 68 | if (simpleProperties.Any()) 69 | { 70 | foreach (var edmProperty in simpleProperties) 71 | { 72 | #> 73 | <#=codeStringGenerator.Property(edmProperty)#> 74 | <# 75 | } 76 | } 77 | 78 | if (complexProperties.Any()) 79 | { 80 | #> 81 | 82 | <# 83 | foreach(var complexProperty in complexProperties) 84 | { 85 | #> 86 | <#=codeStringGenerator.Property(complexProperty)#> 87 | <# 88 | } 89 | } 90 | 91 | var navigationProperties = typeMapper.GetNavigationProperties(entity); 92 | if (navigationProperties.Any()) 93 | { 94 | #> 95 | 96 | <# 97 | foreach (var navigationProperty in navigationProperties) 98 | { 99 | if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) 100 | { 101 | #> 102 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 103 | <# 104 | } 105 | #> 106 | <#=codeStringGenerator.NavigationProperty(navigationProperty)#> 107 | <# 108 | } 109 | } 110 | #> 111 | } 112 | <# 113 | EndNamespace(code); 114 | } 115 | 116 | foreach (var complex in typeMapper.GetItemsToGenerate(itemCollection)) 117 | { 118 | fileManager.StartNewFile(complex.Name + ".cs"); 119 | BeginNamespace(code); 120 | #> 121 | <#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#> 122 | <#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#> 123 | { 124 | <# 125 | var complexProperties = typeMapper.GetComplexProperties(complex); 126 | var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex); 127 | 128 | if (propertiesWithDefaultValues.Any() || complexProperties.Any()) 129 | { 130 | #> 131 | public <#=code.Escape(complex)#>() 132 | { 133 | <# 134 | foreach (var edmProperty in propertiesWithDefaultValues) 135 | { 136 | #> 137 | this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>; 138 | <# 139 | } 140 | 141 | foreach (var complexProperty in complexProperties) 142 | { 143 | #> 144 | this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>(); 145 | <# 146 | } 147 | #> 148 | } 149 | 150 | <# 151 | } 152 | 153 | var simpleProperties = typeMapper.GetSimpleProperties(complex); 154 | if (simpleProperties.Any()) 155 | { 156 | foreach(var edmProperty in simpleProperties) 157 | { 158 | #> 159 | <#=codeStringGenerator.Property(edmProperty)#> 160 | <# 161 | } 162 | } 163 | 164 | if (complexProperties.Any()) 165 | { 166 | #> 167 | 168 | <# 169 | foreach(var edmProperty in complexProperties) 170 | { 171 | #> 172 | <#=codeStringGenerator.Property(edmProperty)#> 173 | <# 174 | } 175 | } 176 | #> 177 | } 178 | <# 179 | EndNamespace(code); 180 | } 181 | 182 | foreach (var enumType in typeMapper.GetEnumItemsToGenerate(itemCollection)) 183 | { 184 | fileManager.StartNewFile(enumType.Name + ".cs"); 185 | BeginNamespace(code); 186 | #> 187 | <#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#> 188 | <# 189 | if (typeMapper.EnumIsFlags(enumType)) 190 | { 191 | #> 192 | [Flags] 193 | <# 194 | } 195 | #> 196 | <#=codeStringGenerator.EnumOpening(enumType)#> 197 | { 198 | <# 199 | var foundOne = false; 200 | 201 | foreach (MetadataItem member in typeMapper.GetEnumMembers(enumType)) 202 | { 203 | foundOne = true; 204 | #> 205 | <#=code.Escape(typeMapper.GetEnumMemberName(member))#> = <#=typeMapper.GetEnumMemberValue(member)#>, 206 | <# 207 | } 208 | 209 | if (foundOne) 210 | { 211 | this.GenerationEnvironment.Remove(this.GenerationEnvironment.Length - 3, 1); 212 | } 213 | #> 214 | } 215 | <# 216 | EndNamespace(code); 217 | } 218 | 219 | fileManager.Process(); 220 | 221 | #> 222 | <#+ 223 | 224 | public void WriteHeader(CodeStringGenerator codeStringGenerator, EntityFrameworkTemplateFileManager fileManager) 225 | { 226 | fileManager.StartHeader(); 227 | #> 228 | //------------------------------------------------------------------------------ 229 | // 230 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#> 231 | // 232 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#> 233 | // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#> 234 | // 235 | //------------------------------------------------------------------------------ 236 | <#=codeStringGenerator.UsingDirectives(inHeader: true)#> 237 | <#+ 238 | fileManager.EndBlock(); 239 | } 240 | 241 | public void BeginNamespace(CodeGenerationTools code) 242 | { 243 | var codeNamespace = code.VsNamespaceSuggestion(); 244 | if (!String.IsNullOrEmpty(codeNamespace)) 245 | { 246 | #> 247 | namespace <#=code.EscapeNamespace(codeNamespace)#> 248 | { 249 | <#+ 250 | PushIndent(" "); 251 | } 252 | } 253 | 254 | public void EndNamespace(CodeGenerationTools code) 255 | { 256 | if (!String.IsNullOrEmpty(code.VsNamespaceSuggestion())) 257 | { 258 | PopIndent(); 259 | #> 260 | } 261 | <#+ 262 | } 263 | } 264 | 265 | public const string TemplateId = "CSharp_DbContext_Types_EF6"; 266 | 267 | public class CodeStringGenerator 268 | { 269 | private readonly CodeGenerationTools _code; 270 | private readonly TypeMapper _typeMapper; 271 | private readonly MetadataTools _ef; 272 | 273 | public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef) 274 | { 275 | ArgumentNotNull(code, "code"); 276 | ArgumentNotNull(typeMapper, "typeMapper"); 277 | ArgumentNotNull(ef, "ef"); 278 | 279 | _code = code; 280 | _typeMapper = typeMapper; 281 | _ef = ef; 282 | } 283 | 284 | public string Property(EdmProperty edmProperty) 285 | { 286 | return string.Format( 287 | CultureInfo.InvariantCulture, 288 | "{0} {1} {2} {{ {3}get; {4}set; }}", 289 | Accessibility.ForProperty(edmProperty), 290 | _typeMapper.GetTypeName(edmProperty.TypeUsage), 291 | _code.Escape(edmProperty), 292 | _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 293 | _code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 294 | } 295 | 296 | public string NavigationProperty(NavigationProperty navProp) 297 | { 298 | var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType()); 299 | return string.Format( 300 | CultureInfo.InvariantCulture, 301 | "{0} {1} {2} {{ {3}get; {4}set; }}", 302 | AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)), 303 | navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, 304 | _code.Escape(navProp), 305 | _code.SpaceAfter(Accessibility.ForGetter(navProp)), 306 | _code.SpaceAfter(Accessibility.ForSetter(navProp))); 307 | } 308 | 309 | public string AccessibilityAndVirtual(string accessibility) 310 | { 311 | return accessibility + (accessibility != "private" ? " virtual" : ""); 312 | } 313 | 314 | public string EntityClassOpening(EntityType entity) 315 | { 316 | return string.Format( 317 | CultureInfo.InvariantCulture, 318 | "{0} {1}partial class {2}{3}", 319 | Accessibility.ForType(entity), 320 | _code.SpaceAfter(_code.AbstractOption(entity)), 321 | _code.Escape(entity), 322 | _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType))); 323 | } 324 | 325 | public string EnumOpening(SimpleType enumType) 326 | { 327 | return string.Format( 328 | CultureInfo.InvariantCulture, 329 | "{0} enum {1} : {2}", 330 | Accessibility.ForType(enumType), 331 | _code.Escape(enumType), 332 | _code.Escape(_typeMapper.UnderlyingClrType(enumType))); 333 | } 334 | 335 | public void WriteFunctionParameters(EdmFunction edmFunction, Action writeParameter) 336 | { 337 | var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); 338 | foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable)) 339 | { 340 | var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"; 341 | var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")"; 342 | var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))"; 343 | writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit); 344 | } 345 | } 346 | 347 | public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace) 348 | { 349 | var parameters = _typeMapper.GetParameters(edmFunction); 350 | 351 | return string.Format( 352 | CultureInfo.InvariantCulture, 353 | "{0} IQueryable<{1}> {2}({3})", 354 | AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), 355 | _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), 356 | _code.Escape(edmFunction), 357 | string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray())); 358 | } 359 | 360 | public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace) 361 | { 362 | var parameters = _typeMapper.GetParameters(edmFunction); 363 | 364 | return string.Format( 365 | CultureInfo.InvariantCulture, 366 | "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});", 367 | _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), 368 | edmFunction.NamespaceName, 369 | edmFunction.Name, 370 | string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()), 371 | _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))); 372 | } 373 | 374 | public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 375 | { 376 | var parameters = _typeMapper.GetParameters(edmFunction); 377 | var returnType = _typeMapper.GetReturnType(edmFunction); 378 | 379 | var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()); 380 | if (includeMergeOption) 381 | { 382 | paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption"; 383 | } 384 | 385 | return string.Format( 386 | CultureInfo.InvariantCulture, 387 | "{0} {1} {2}({3})", 388 | AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), 389 | returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", 390 | _code.Escape(edmFunction), 391 | paramList); 392 | } 393 | 394 | public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) 395 | { 396 | var parameters = _typeMapper.GetParameters(edmFunction); 397 | var returnType = _typeMapper.GetReturnType(edmFunction); 398 | 399 | var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())); 400 | if (includeMergeOption) 401 | { 402 | callParams = ", mergeOption" + callParams; 403 | } 404 | 405 | return string.Format( 406 | CultureInfo.InvariantCulture, 407 | "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});", 408 | returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", 409 | edmFunction.Name, 410 | callParams); 411 | } 412 | 413 | public string DbSet(EntitySet entitySet) 414 | { 415 | return string.Format( 416 | CultureInfo.InvariantCulture, 417 | "{0} virtual DbSet<{1}> {2} {{ get; set; }}", 418 | Accessibility.ForReadOnlyProperty(entitySet), 419 | _typeMapper.GetTypeName(entitySet.ElementType), 420 | _code.Escape(entitySet)); 421 | } 422 | 423 | public string UsingDirectives(bool inHeader, bool includeCollections = true) 424 | { 425 | return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion()) 426 | ? string.Format( 427 | CultureInfo.InvariantCulture, 428 | "{0}using System;{1}" + 429 | "{2}", 430 | inHeader ? Environment.NewLine : "", 431 | includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "", 432 | inHeader ? "" : Environment.NewLine) 433 | : ""; 434 | } 435 | } 436 | 437 | public class TypeMapper 438 | { 439 | private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName"; 440 | 441 | private readonly System.Collections.IList _errors; 442 | private readonly CodeGenerationTools _code; 443 | private readonly MetadataTools _ef; 444 | 445 | public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors) 446 | { 447 | ArgumentNotNull(code, "code"); 448 | ArgumentNotNull(ef, "ef"); 449 | ArgumentNotNull(errors, "errors"); 450 | 451 | _code = code; 452 | _ef = ef; 453 | _errors = errors; 454 | } 455 | 456 | public static string FixNamespaces(string typeName) 457 | { 458 | return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial."); 459 | } 460 | 461 | public string GetTypeName(TypeUsage typeUsage) 462 | { 463 | return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null); 464 | } 465 | 466 | public string GetTypeName(EdmType edmType) 467 | { 468 | return GetTypeName(edmType, isNullable: null, modelNamespace: null); 469 | } 470 | 471 | public string GetTypeName(TypeUsage typeUsage, string modelNamespace) 472 | { 473 | return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace); 474 | } 475 | 476 | public string GetTypeName(EdmType edmType, string modelNamespace) 477 | { 478 | return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace); 479 | } 480 | 481 | public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace) 482 | { 483 | if (edmType == null) 484 | { 485 | return null; 486 | } 487 | 488 | var collectionType = edmType as CollectionType; 489 | if (collectionType != null) 490 | { 491 | return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace)); 492 | } 493 | 494 | var typeName = _code.Escape(edmType.MetadataProperties 495 | .Where(p => p.Name == ExternalTypeNameAttributeName) 496 | .Select(p => (string)p.Value) 497 | .FirstOrDefault()) 498 | ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ? 499 | _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) : 500 | _code.Escape(edmType)); 501 | 502 | if (edmType is StructuralType) 503 | { 504 | return typeName; 505 | } 506 | 507 | if (edmType is SimpleType) 508 | { 509 | var clrType = UnderlyingClrType(edmType); 510 | if (!IsEnumType(edmType)) 511 | { 512 | typeName = _code.Escape(clrType); 513 | } 514 | 515 | typeName = FixNamespaces(typeName); 516 | 517 | return clrType.IsValueType && isNullable == true ? 518 | String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) : 519 | typeName; 520 | } 521 | 522 | throw new ArgumentException("edmType"); 523 | } 524 | 525 | public Type UnderlyingClrType(EdmType edmType) 526 | { 527 | ArgumentNotNull(edmType, "edmType"); 528 | 529 | var primitiveType = edmType as PrimitiveType; 530 | if (primitiveType != null) 531 | { 532 | return primitiveType.ClrEquivalentType; 533 | } 534 | 535 | if (IsEnumType(edmType)) 536 | { 537 | return GetEnumUnderlyingType(edmType).ClrEquivalentType; 538 | } 539 | 540 | return typeof(object); 541 | } 542 | 543 | public object GetEnumMemberValue(MetadataItem enumMember) 544 | { 545 | ArgumentNotNull(enumMember, "enumMember"); 546 | 547 | var valueProperty = enumMember.GetType().GetProperty("Value"); 548 | return valueProperty == null ? null : valueProperty.GetValue(enumMember, null); 549 | } 550 | 551 | public string GetEnumMemberName(MetadataItem enumMember) 552 | { 553 | ArgumentNotNull(enumMember, "enumMember"); 554 | 555 | var nameProperty = enumMember.GetType().GetProperty("Name"); 556 | return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null); 557 | } 558 | 559 | public System.Collections.IEnumerable GetEnumMembers(EdmType enumType) 560 | { 561 | ArgumentNotNull(enumType, "enumType"); 562 | 563 | var membersProperty = enumType.GetType().GetProperty("Members"); 564 | return membersProperty != null 565 | ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null) 566 | : Enumerable.Empty(); 567 | } 568 | 569 | public bool EnumIsFlags(EdmType enumType) 570 | { 571 | ArgumentNotNull(enumType, "enumType"); 572 | 573 | var isFlagsProperty = enumType.GetType().GetProperty("IsFlags"); 574 | return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null); 575 | } 576 | 577 | public bool IsEnumType(GlobalItem edmType) 578 | { 579 | ArgumentNotNull(edmType, "edmType"); 580 | 581 | return edmType.GetType().Name == "EnumType"; 582 | } 583 | 584 | public PrimitiveType GetEnumUnderlyingType(EdmType enumType) 585 | { 586 | ArgumentNotNull(enumType, "enumType"); 587 | 588 | return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null); 589 | } 590 | 591 | public string CreateLiteral(object value) 592 | { 593 | if (value == null || value.GetType() != typeof(TimeSpan)) 594 | { 595 | return _code.CreateLiteral(value); 596 | } 597 | 598 | return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks); 599 | } 600 | 601 | public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable types, string sourceFile) 602 | { 603 | ArgumentNotNull(types, "types"); 604 | ArgumentNotNull(sourceFile, "sourceFile"); 605 | 606 | var hash = new HashSet(StringComparer.InvariantCultureIgnoreCase); 607 | if (types.Any(item => !hash.Add(item))) 608 | { 609 | _errors.Add( 610 | new CompilerError(sourceFile, -1, -1, "6023", 611 | String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict")))); 612 | return false; 613 | } 614 | return true; 615 | } 616 | 617 | public IEnumerable GetEnumItemsToGenerate(IEnumerable itemCollection) 618 | { 619 | return GetItemsToGenerate(itemCollection) 620 | .Where(e => IsEnumType(e)); 621 | } 622 | 623 | public IEnumerable GetItemsToGenerate(IEnumerable itemCollection) where T: EdmType 624 | { 625 | return itemCollection 626 | .OfType() 627 | .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName)) 628 | .OrderBy(i => i.Name); 629 | } 630 | 631 | public IEnumerable GetAllGlobalItems(IEnumerable itemCollection) 632 | { 633 | return itemCollection 634 | .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i)) 635 | .Select(g => GetGlobalItemName(g)); 636 | } 637 | 638 | public string GetGlobalItemName(GlobalItem item) 639 | { 640 | if (item is EdmType) 641 | { 642 | return ((EdmType)item).Name; 643 | } 644 | else 645 | { 646 | return ((EntityContainer)item).Name; 647 | } 648 | } 649 | 650 | public IEnumerable GetSimpleProperties(EntityType type) 651 | { 652 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); 653 | } 654 | 655 | public IEnumerable GetSimpleProperties(ComplexType type) 656 | { 657 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); 658 | } 659 | 660 | public IEnumerable GetComplexProperties(EntityType type) 661 | { 662 | return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); 663 | } 664 | 665 | public IEnumerable GetComplexProperties(ComplexType type) 666 | { 667 | return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); 668 | } 669 | 670 | public IEnumerable GetPropertiesWithDefaultValues(EntityType type) 671 | { 672 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); 673 | } 674 | 675 | public IEnumerable GetPropertiesWithDefaultValues(ComplexType type) 676 | { 677 | return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); 678 | } 679 | 680 | public IEnumerable GetNavigationProperties(EntityType type) 681 | { 682 | return type.NavigationProperties.Where(np => np.DeclaringType == type); 683 | } 684 | 685 | public IEnumerable GetCollectionNavigationProperties(EntityType type) 686 | { 687 | return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many); 688 | } 689 | 690 | public FunctionParameter GetReturnParameter(EdmFunction edmFunction) 691 | { 692 | ArgumentNotNull(edmFunction, "edmFunction"); 693 | 694 | var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters"); 695 | return returnParamsProperty == null 696 | ? edmFunction.ReturnParameter 697 | : ((IEnumerable)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault(); 698 | } 699 | 700 | public bool IsComposable(EdmFunction edmFunction) 701 | { 702 | ArgumentNotNull(edmFunction, "edmFunction"); 703 | 704 | var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute"); 705 | return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null); 706 | } 707 | 708 | public IEnumerable GetParameters(EdmFunction edmFunction) 709 | { 710 | return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); 711 | } 712 | 713 | public TypeUsage GetReturnType(EdmFunction edmFunction) 714 | { 715 | var returnParam = GetReturnParameter(edmFunction); 716 | return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage); 717 | } 718 | 719 | public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption) 720 | { 721 | var returnType = GetReturnType(edmFunction); 722 | return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType; 723 | } 724 | } 725 | 726 | public static void ArgumentNotNull(T arg, string name) where T : class 727 | { 728 | if (arg == null) 729 | { 730 | throw new ArgumentNullException(name); 731 | } 732 | } 733 | #> --------------------------------------------------------------------------------