├── .gitattributes ├── .gitignore ├── EF6DBFirstDemo.sln ├── EF6DBFirstDemo ├── App.config ├── Course.cs ├── EF6DBFirstDemo.csproj ├── GetCoursesByStudentId_Result.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── ReadMe.txt ├── School.Context.cs ├── School.Context.tt ├── School.Designer.cs ├── School.cs ├── School.edmx ├── School.edmx.diagram ├── School.tt ├── SchoolDB.mdf ├── Standard.cs ├── Student.cs ├── StudentAddress.cs ├── Teacher.cs ├── View_StudentCourse.cs └── packages.config ├── LICENSE.txt └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /EF6DBFirstDemo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.10 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF6DBFirstDemo", "EF6DBFirstDemo\EF6DBFirstDemo.csproj", "{EFB44BF1-7850-44BC-9544-1F47CEDBF7E9}" 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 | {EFB44BF1-7850-44BC-9544-1F47CEDBF7E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {EFB44BF1-7850-44BC-9544-1F47CEDBF7E9}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {EFB44BF1-7850-44BC-9544-1F47CEDBF7E9}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {EFB44BF1-7850-44BC-9544-1F47CEDBF7E9}.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 = {231DE66E-B080-4002-B5D6-D8F062ABD6D1} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/Course.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Course 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Course() 19 | { 20 | this.Students = new HashSet(); 21 | } 22 | 23 | public int CourseId { get; set; } 24 | public string CourseName { get; set; } 25 | public System.Data.Entity.Spatial.DbGeography Location { get; set; } 26 | public Nullable TeacherId { get; set; } 27 | 28 | public virtual Teacher Teacher { get; set; } 29 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 30 | public virtual ICollection Students { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/EF6DBFirstDemo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EFB44BF1-7850-44BC-9544-1F47CEDBF7E9} 8 | Exe 9 | EF6DBFirstDemo 10 | EF6DBFirstDemo 11 | v4.6.1 12 | 512 13 | true 14 | publish\ 15 | true 16 | Disk 17 | false 18 | Foreground 19 | 7 20 | Days 21 | false 22 | false 23 | true 24 | 0 25 | 1.0.0.%2a 26 | false 27 | false 28 | true 29 | 30 | 31 | AnyCPU 32 | true 33 | full 34 | false 35 | bin\Debug\ 36 | DEBUG;TRACE 37 | prompt 38 | 4 39 | 40 | 41 | AnyCPU 42 | pdbonly 43 | true 44 | bin\Release\ 45 | TRACE 46 | prompt 47 | 4 48 | 49 | 50 | 51 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll 52 | 53 | 54 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | School.tt 71 | 72 | 73 | School.tt 74 | 75 | 76 | 77 | 78 | True 79 | True 80 | School.Context.tt 81 | 82 | 83 | True 84 | True 85 | School.tt 86 | 87 | 88 | True 89 | True 90 | School.edmx 91 | 92 | 93 | School.tt 94 | 95 | 96 | School.tt 97 | 98 | 99 | School.tt 100 | 101 | 102 | School.tt 103 | 104 | 105 | School.tt 106 | 107 | 108 | 109 | 110 | 111 | 112 | EntityModelCodeGenerator 113 | School.Designer.cs 114 | 115 | 116 | School.edmx 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | TextTemplatingFileGenerator 126 | School.edmx 127 | School.Context.cs 128 | 129 | 130 | TextTemplatingFileGenerator 131 | School.edmx 132 | School.cs 133 | 134 | 135 | Always 136 | 137 | 138 | 139 | 140 | False 141 | Microsoft .NET Framework 4.6.1 %28x86 and x64%29 142 | true 143 | 144 | 145 | False 146 | .NET Framework 3.5 SP1 147 | false 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/GetCoursesByStudentId_Result.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | 14 | public partial class GetCoursesByStudentId_Result 15 | { 16 | public Nullable courseid { get; set; } 17 | public string coursename { get; set; } 18 | public Nullable TeacherId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Entity; 4 | using System.Data.Entity.Infrastructure; 5 | using System.Data.Entity.Spatial; 6 | using System.Linq; 7 | 8 | namespace EF6DBFirstDemo 9 | { 10 | internal class Program 11 | { 12 | private static void Main(string[] args) 13 | { 14 | AddUpdateDeleteEntityInConnectedScenario(); 15 | AddUpdateEntityInDisconnectedScenario(); 16 | LinqToEntitiesQueries(); 17 | FindEntity(); 18 | LazyLoading(); 19 | ExplicitLoading(); 20 | ExecuteRawSQLusingSqlQuery(); 21 | ExecuteSqlCommand(); 22 | DynamicProxy(); 23 | ReadDataUsingStoredProcedure(); 24 | ChangeTracker(); 25 | SpatialDataType(); 26 | EntityEntry(); 27 | OptimisticConcurrency(); 28 | TransactionSupport(); 29 | SetEntityState(); 30 | 31 | Console.ReadLine(); 32 | } 33 | 34 | public static void AddUpdateDeleteEntityInConnectedScenario() 35 | { 36 | Console.WriteLine("*** AddUpdateDeleteEntityInConnectedScenario Starts ***"); 37 | 38 | using (var context = new SchoolDBEntities()) 39 | { 40 | //Log DB commands to console 41 | context.Database.Log = Console.WriteLine; 42 | 43 | //Add a new student and address 44 | var newStudent = context.Students.Add(new Student() { StudentName = "Jonathan", StudentAddress = new StudentAddress() { Address1 = "1, Harbourside", City = "Jersey City", State = "NJ" } }); 45 | context.SaveChanges(); // Executes Insert command 46 | 47 | //Edit student name 48 | newStudent.StudentName = "Alex"; 49 | context.SaveChanges(); // Executes Update command 50 | 51 | //Remove student 52 | context.Students.Remove(newStudent); 53 | context.SaveChanges(); // Executes Delete command 54 | } 55 | 56 | Console.WriteLine("*** AddUpdateDeleteEntityInConnectedScenario Ends ***"); 57 | } 58 | 59 | public static void AddUpdateEntityInDisconnectedScenario() 60 | { 61 | Console.WriteLine("*** AddUpdateEntityInDisconnectedScenario Starts ***"); 62 | 63 | // disconnected entities 64 | var newStudent = new Student() { StudentName = "Bill" }; 65 | var existingStudent = new Student() { StudentID = 10, StudentName = "Chris" }; 66 | 67 | using (var context = new SchoolDBEntities()) 68 | { 69 | //Log DB commands to console 70 | context.Database.Log = Console.WriteLine; 71 | 72 | context.Entry(newStudent).State = newStudent.StudentID == 0 ? EntityState.Added : EntityState.Modified; 73 | context.Entry(existingStudent).State = existingStudent.StudentID == 0 ? EntityState.Added : EntityState.Modified; 74 | 75 | context.SaveChanges(); // Executes Delete command 76 | } 77 | 78 | Console.WriteLine("*** AddUpdateEntityInDisconnectedScenario Ends ***"); 79 | } 80 | 81 | public static void LinqToEntitiesQueries() 82 | { 83 | Console.WriteLine("*** LinqToEntitiesQueries Starts ***"); 84 | 85 | using (var context = new SchoolDBEntities()) 86 | { 87 | //Log DB commands to console 88 | context.Database.Log = Console.WriteLine; 89 | 90 | //Retrieve students whose name is Bill - Linq-to-Entities Query Syntax 91 | var students = (from s in context.Students 92 | where s.StudentName == "Bill" 93 | select s).ToList(); 94 | 95 | //Retrieve students with the same name - Linq-to-Entities Method Syntax 96 | var studentsWithSameName = context.Students 97 | .GroupBy(s => s.StudentName) 98 | .Where(g => g.Count() > 1) 99 | .Select(g => g.Key); 100 | 101 | Console.WriteLine("Students with same name"); 102 | foreach (var stud in studentsWithSameName) 103 | { 104 | Console.WriteLine(stud); 105 | } 106 | 107 | //Retrieve students of standard 1 108 | var standard1Students = context.Students 109 | .Where(s => s.StandardId == 1) 110 | .ToList(); 111 | } 112 | 113 | Console.WriteLine("*** LinqToEntitiesQueries Ends ***"); 114 | } 115 | 116 | public static void FindEntity() 117 | { 118 | Console.WriteLine("*** FindEntity Starts ***"); 119 | 120 | using (var context = new SchoolDBEntities()) 121 | { 122 | context.Database.Log = Console.WriteLine; 123 | 124 | var stud = context.Students.Find(1); 125 | 126 | Console.WriteLine(stud.StudentName + " found"); 127 | } 128 | 129 | Console.WriteLine("*** FindEntity Ends ***"); 130 | } 131 | 132 | public static void LazyLoading() 133 | { 134 | Console.WriteLine("*** LazyLoading Starts ***"); 135 | 136 | using (var context = new SchoolDBEntities()) 137 | { 138 | context.Database.Log = Console.Write; 139 | 140 | Student student = context.Students.Where(s => s.StudentID == 1).FirstOrDefault(); 141 | 142 | Console.WriteLine("*** Retrieve standard from the database ***"); 143 | Standard std = student.Standard; 144 | } 145 | 146 | Console.WriteLine("*** LazyLoading Ends ***"); 147 | } 148 | 149 | public static void ExplicitLoading() 150 | { 151 | Console.WriteLine("*** ExplicitLoading Starts ***"); 152 | 153 | using (var context = new SchoolDBEntities()) 154 | { 155 | context.Database.Log = Console.Write; 156 | 157 | Student std = context.Students 158 | .Where(s => s.StudentID == 1) 159 | .FirstOrDefault(); 160 | 161 | //Loading Standard for Student (seperate SQL query) 162 | context.Entry(std).Reference(s => s.Standard).Load(); 163 | 164 | //Loading Courses for Student (seperate SQL query) 165 | context.Entry(std).Collection(s => s.Courses).Load(); 166 | } 167 | 168 | Console.WriteLine("*** ExplicitLoading Ends ***"); 169 | } 170 | 171 | public static void ExecuteRawSQLusingSqlQuery() 172 | { 173 | Console.WriteLine("*** ExecuteRawSQLusingSqlQuery Starts ***"); 174 | 175 | using (var context = new SchoolDBEntities()) 176 | { 177 | context.Database.Log = Console.Write; 178 | 179 | var studentList = context.Students.SqlQuery("Select * from Student").ToList(); 180 | 181 | var student = context.Students.SqlQuery("Select StudentId, StudentName, StandardId, RowVersion from Student where StudentId = 1").ToList(); 182 | } 183 | 184 | Console.WriteLine("*** ExecuteRawSQLusingSqlQuery Ends ***"); 185 | } 186 | 187 | public static void ExecuteSqlCommand() 188 | { 189 | Console.WriteLine("*** ExecuteSqlCommand Starts ***"); 190 | 191 | using (var context = new SchoolDBEntities()) 192 | { 193 | context.Database.Log = Console.Write; 194 | 195 | //Insert command 196 | int noOfRowInsert = context.Database.ExecuteSqlCommand("insert into student(studentname) values('Robert')"); 197 | 198 | //Update command 199 | int noOfRowUpdate = context.Database.ExecuteSqlCommand("Update student set studentname ='Mark' where studentname = 'Robert'"); 200 | 201 | //Delete command 202 | int noOfRowDeleted = context.Database.ExecuteSqlCommand("delete from student where studentname = 'Mark'"); 203 | } 204 | 205 | Console.WriteLine("*** ExecuteSqlCommand Ends ***"); 206 | } 207 | 208 | public static void DynamicProxy() 209 | { 210 | Console.WriteLine("*** DynamicProxy Starts ***"); 211 | 212 | using (var context = new SchoolDBEntities()) 213 | { 214 | var student = context.Students.Where(s => s.StudentName == "Bill") 215 | .FirstOrDefault(); 216 | 217 | Console.WriteLine("Proxy Type: {0}", student.GetType().Name); 218 | Console.WriteLine("Underlying Entity Type: {0}", student.GetType().BaseType); 219 | 220 | //Disable Proxy creation 221 | context.Configuration.ProxyCreationEnabled = false; 222 | 223 | Console.WriteLine("Proxy Creation Disabled"); 224 | 225 | var student1 = context.Students.Where(s => s.StudentName == "Steve") 226 | .FirstOrDefault(); 227 | 228 | Console.WriteLine("Entity Type: {0}", student1.GetType().Name); 229 | } 230 | 231 | Console.WriteLine("*** DynamicProxy Ends ***"); 232 | } 233 | 234 | public static void ReadDataUsingStoredProcedure() 235 | { 236 | Console.WriteLine("*** ReadDataUsingStoredProcedure Starts ***"); 237 | 238 | using (var context = new SchoolDBEntities()) 239 | { 240 | context.Database.Log = Console.Write; 241 | //get all the courses of student whose id is 1 242 | var courses = context.GetCoursesByStudentId(1); 243 | //Set Course entity as return type of GetCoursesByStudentId function 244 | //Open ModelBrowser -> Function Imports -> Right click on GetCoursesByStudentId and Edit 245 | //Change Returns a Collection of to Course Entity from Complex Type 246 | //uncomment following lines 247 | //foreach (Course cs in courses) 248 | // Console.WriteLine(cs.CourseName); 249 | } 250 | 251 | Console.WriteLine("*** ReadDataUsingStoredProcedure Ends ***"); 252 | } 253 | 254 | public static void ChangeTracker() 255 | { 256 | Console.WriteLine("*** ChangeTracker Starts ***"); 257 | 258 | using (var context = new SchoolDBEntities()) 259 | { 260 | context.Configuration.ProxyCreationEnabled = false; 261 | 262 | var student = context.Students.Add(new Student() { StudentName = "Mili" }); 263 | DisplayTrackedEntities(context); 264 | 265 | Console.WriteLine("Retrieve Student"); 266 | var existingStudent = context.Students.Find(1); 267 | 268 | DisplayTrackedEntities(context); 269 | 270 | Console.WriteLine("Retrieve Standard"); 271 | var standard = context.Standards.Find(1); 272 | 273 | DisplayTrackedEntities(context); 274 | 275 | Console.WriteLine("Editing Standard"); 276 | standard.StandardName = "Grade 5"; 277 | 278 | DisplayTrackedEntities(context); 279 | 280 | Console.WriteLine("Remove Student"); 281 | context.Students.Remove(existingStudent); 282 | DisplayTrackedEntities(context); 283 | } 284 | 285 | Console.WriteLine("*** ChangeTracker Ends ***"); 286 | } 287 | 288 | private static void DisplayTrackedEntities(SchoolDBEntities context) 289 | { 290 | Console.WriteLine("Context is tracking {0} entities.", context.ChangeTracker.Entries().Count()); 291 | DbChangeTracker changeTracker = context.ChangeTracker; 292 | var entries = changeTracker.Entries(); 293 | foreach (var entry in entries) 294 | { 295 | Console.WriteLine("Entity Name: {0}", entry.Entity.GetType().FullName); 296 | Console.WriteLine("Status: {0}", entry.State); 297 | } 298 | } 299 | 300 | public static void SpatialDataType() 301 | { 302 | Console.WriteLine("*** SpatialDataType Starts ***"); 303 | 304 | using (var context = new SchoolDBEntities()) 305 | { 306 | context.Database.Log = Console.Write; 307 | //Add Location using System.Data.Entity.Spatial.DbGeography 308 | context.Courses.Add(new Course() { CourseName = "New Course from SpatialDataTypeDemo", Location = DbGeography.FromText("POINT(-122.360 47.656)") }); 309 | 310 | context.SaveChanges(); 311 | } 312 | 313 | Console.WriteLine("*** SpatialDataTypeDemo Ends ***"); 314 | } 315 | 316 | public static void EntityEntry() 317 | { 318 | Console.WriteLine("*** EntityEntry Starts ***"); 319 | 320 | using (var context = new SchoolDBEntities()) 321 | { 322 | //get student whose StudentId is 1 323 | var student = context.Students.Find(1); 324 | 325 | //edit student name 326 | student.StudentName = "Monica"; 327 | 328 | //get DbEntityEntry object for student entity object 329 | var entry = context.Entry(student); 330 | 331 | //get entity information e.g. full name 332 | Console.WriteLine("Entity Name: {0}", entry.Entity.GetType().FullName); 333 | 334 | //get current EntityState 335 | Console.WriteLine("Entity State: {0}", entry.State); 336 | 337 | Console.WriteLine("********Property Values********"); 338 | 339 | foreach (var propertyName in entry.CurrentValues.PropertyNames) 340 | { 341 | Console.WriteLine("Property Name: {0}", propertyName); 342 | 343 | //get original value 344 | var orgVal = entry.OriginalValues[propertyName]; 345 | Console.WriteLine(" Original Value: {0}", orgVal); 346 | 347 | //get current values 348 | var curVal = entry.CurrentValues[propertyName]; 349 | Console.WriteLine(" Current Value: {0}", curVal); 350 | } 351 | } 352 | 353 | Console.WriteLine("*** EntityEntryDemo Ends ***"); 354 | } 355 | 356 | public static void TransactionSupport() 357 | { 358 | Console.WriteLine("*** TransactionSupport Starts ***"); 359 | 360 | using (var context = new SchoolDBEntities()) 361 | { 362 | Console.WriteLine("Built-in Transaction"); 363 | //Log DB commands to console 364 | context.Database.Log = Console.WriteLine; 365 | 366 | //Add a new student and address 367 | context.Students.Add(new Student() { StudentName = "Kapil" }); 368 | 369 | var existingStudent = context.Students.Find(10); 370 | //Edit student name 371 | existingStudent.StudentName = "Alex"; 372 | 373 | context.SaveChanges(); // Executes Insert & Update command under one transaction 374 | } 375 | 376 | Console.WriteLine("External Transaction"); 377 | using (var context = new SchoolDBEntities()) 378 | { 379 | context.Database.Log = Console.Write; 380 | 381 | using (DbContextTransaction transaction = context.Database.BeginTransaction()) 382 | { 383 | try 384 | { 385 | context.Students.Add(new Student() 386 | { 387 | StudentName = "Arjun" 388 | }); 389 | context.SaveChanges(); 390 | 391 | context.Courses.Add(new Course() { CourseName = "Entity Framework" }); 392 | context.SaveChanges(); 393 | 394 | transaction.Commit(); 395 | } 396 | catch (Exception ex) 397 | { 398 | transaction.Rollback(); 399 | Console.WriteLine("Error occurred."); 400 | } 401 | } 402 | } 403 | 404 | Console.WriteLine("*** TransactionSupport Ends ***"); 405 | } 406 | 407 | public static void SetEntityState() 408 | { 409 | Console.WriteLine("*** SetEntityState Starts ***"); 410 | 411 | var student = new Student() 412 | { 413 | StudentID = 1, // root entity with key 414 | StudentName = "Bill", 415 | StandardId = 1, 416 | Standard = new Standard() //Child entity (with key value) 417 | { 418 | StandardId = 1, 419 | StandardName = "Grade 1" 420 | }, 421 | Courses = new List() { 422 | new Course(){ CourseName = "Machine Language" }, //Child entity (empty key) 423 | new Course(){ CourseId = 2 } //Child entity (with key value) 424 | } 425 | }; 426 | 427 | using (var context = new SchoolDBEntities()) 428 | { 429 | context.Entry(student).State = EntityState.Modified; 430 | 431 | foreach (var entity in context.ChangeTracker.Entries()) 432 | { 433 | Console.WriteLine("{0}: {1}", entity.Entity.GetType().Name, entity.State); 434 | } 435 | } 436 | 437 | Console.WriteLine("*** SetEntityState Ends ***"); 438 | } 439 | 440 | public static void OptimisticConcurrency() 441 | { 442 | Console.WriteLine("*** OptimisticConcurrency Starts ***"); 443 | 444 | Student student = null; 445 | 446 | using (var context = new SchoolDBEntities()) 447 | { 448 | student = context.Students.First(); 449 | } 450 | 451 | //Edit student name 452 | student.StudentName = "Robin"; 453 | 454 | using (var context = new SchoolDBEntities()) 455 | { 456 | context.Database.Log = Console.Write; 457 | 458 | try 459 | { 460 | context.Entry(student).State = EntityState.Modified; 461 | context.SaveChanges(); 462 | 463 | Console.WriteLine("Student saved successfully."); 464 | } 465 | catch (DbUpdateConcurrencyException ex) 466 | { 467 | Console.WriteLine("Concurrency Exception Occurred."); 468 | } 469 | } 470 | 471 | Console.WriteLine("*** OptimisticConcurrency Ends ***"); 472 | } 473 | } 474 | } -------------------------------------------------------------------------------- /EF6DBFirstDemo/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("EF6DBFirstDemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("EF6DBFirstDemo")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2018")] 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("efb44bf1-7850-44bc-9544-1f47cedbf7e9")] 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 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/ReadMe.txt: -------------------------------------------------------------------------------- 1 | Instruction to run this demo project: 2 | - Attach SchoolDB.mdf in your local MS SQL Server 2012 or above 3 | - Verify the connection string in App.config and make sure that it is pointing to your local DB server. 4 | - You may delete School.edmx and add a new Entity Data Model named 'School'. -------------------------------------------------------------------------------- /EF6DBFirstDemo/School.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | using System.Data.Entity; 14 | using System.Data.Entity.Infrastructure; 15 | using System.Data.Entity.Core.Objects; 16 | using System.Linq; 17 | 18 | public partial class SchoolDBEntities : DbContext 19 | { 20 | public SchoolDBEntities() 21 | : base("name=SchoolDBEntities") 22 | { 23 | } 24 | 25 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 26 | { 27 | throw new UnintentionalCodeFirstException(); 28 | } 29 | 30 | public virtual DbSet Courses { get; set; } 31 | public virtual DbSet Standards { get; set; } 32 | public virtual DbSet Students { get; set; } 33 | public virtual DbSet StudentAddresses { get; set; } 34 | public virtual DbSet Teachers { get; set; } 35 | public virtual DbSet View_StudentCourse { get; set; } 36 | 37 | public virtual ObjectResult GetCoursesByStudentId(Nullable studentId) 38 | { 39 | var studentIdParameter = studentId.HasValue ? 40 | new ObjectParameter("StudentId", studentId) : 41 | new ObjectParameter("StudentId", typeof(int)); 42 | 43 | return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("GetCoursesByStudentId", studentIdParameter); 44 | } 45 | 46 | public virtual ObjectResult GetCoursesByStudentId(Nullable studentId, MergeOption mergeOption) 47 | { 48 | var studentIdParameter = studentId.HasValue ? 49 | new ObjectParameter("StudentId", studentId) : 50 | new ObjectParameter("StudentId", typeof(int)); 51 | 52 | return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("GetCoursesByStudentId", mergeOption, studentIdParameter); 53 | } 54 | 55 | public virtual int sp_DeleteStudent(Nullable studentId) 56 | { 57 | var studentIdParameter = studentId.HasValue ? 58 | new ObjectParameter("StudentId", studentId) : 59 | new ObjectParameter("StudentId", typeof(int)); 60 | 61 | return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("sp_DeleteStudent", studentIdParameter); 62 | } 63 | 64 | public virtual ObjectResult> sp_InsertStudentInfo(Nullable standardId, string studentName) 65 | { 66 | var standardIdParameter = standardId.HasValue ? 67 | new ObjectParameter("StandardId", standardId) : 68 | new ObjectParameter("StandardId", typeof(int)); 69 | 70 | var studentNameParameter = studentName != null ? 71 | new ObjectParameter("StudentName", studentName) : 72 | new ObjectParameter("StudentName", typeof(string)); 73 | 74 | return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction>("sp_InsertStudentInfo", standardIdParameter, studentNameParameter); 75 | } 76 | 77 | public virtual int sp_UpdateStudent(Nullable studentId, Nullable standardId, string studentName) 78 | { 79 | var studentIdParameter = studentId.HasValue ? 80 | new ObjectParameter("StudentId", studentId) : 81 | new ObjectParameter("StudentId", typeof(int)); 82 | 83 | var standardIdParameter = standardId.HasValue ? 84 | new ObjectParameter("StandardId", standardId) : 85 | new ObjectParameter("StandardId", typeof(int)); 86 | 87 | var studentNameParameter = studentName != null ? 88 | new ObjectParameter("StudentName", studentName) : 89 | new ObjectParameter("StudentName", typeof(string)); 90 | 91 | return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("sp_UpdateStudent", studentIdParameter, standardIdParameter, studentNameParameter); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/School.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 = @"School.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 | #> -------------------------------------------------------------------------------- /EF6DBFirstDemo/School.Designer.cs: -------------------------------------------------------------------------------- 1 | // T4 code generation is enabled for model 'D:\EntityFramework\EFProjects\EF6DBFirstDemo\EF6DBFirstDemo\School.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...'. -------------------------------------------------------------------------------- /EF6DBFirstDemo/School.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 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/School.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 | 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 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | SELECT 179 | [View_StudentCourse].[StudentID] AS [StudentID], 180 | [View_StudentCourse].[StudentName] AS [StudentName], 181 | [View_StudentCourse].[CourseId] AS [CourseId], 182 | [View_StudentCourse].[CourseName] AS [CourseName] 183 | FROM [dbo].[View_StudentCourse] AS [View_StudentCourse] 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/School.edmx.diagram: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/School.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 = @"School.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 | #> -------------------------------------------------------------------------------- /EF6DBFirstDemo/SchoolDB.mdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzzprojects/EF6-DBFirst-Demo/5a982e9730f6d8c9ea3bd3dfb49241354d6cbaad/EF6DBFirstDemo/SchoolDB.mdf -------------------------------------------------------------------------------- /EF6DBFirstDemo/Standard.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Standard 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Standard() 19 | { 20 | this.Students = new HashSet(); 21 | this.Teachers = new HashSet(); 22 | } 23 | 24 | public int StandardId { get; set; } 25 | public string StandardName { get; set; } 26 | public string Description { get; set; } 27 | 28 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 29 | public virtual ICollection Students { get; set; } 30 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 31 | public virtual ICollection Teachers { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/Student.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Student 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Student() 19 | { 20 | this.Courses = new HashSet(); 21 | } 22 | 23 | public int StudentID { get; set; } 24 | public string StudentName { get; set; } 25 | public Nullable StandardId { get; set; } 26 | public byte[] RowVersion { get; set; } 27 | 28 | public virtual Standard Standard { get; set; } 29 | public virtual StudentAddress StudentAddress { get; set; } 30 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 31 | public virtual ICollection Courses { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/StudentAddress.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class StudentAddress 16 | { 17 | public int StudentID { get; set; } 18 | public string Address1 { get; set; } 19 | public string Address2 { get; set; } 20 | public string City { get; set; } 21 | public string State { get; set; } 22 | 23 | public virtual Student Student { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/Teacher.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class Teacher 16 | { 17 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 18 | public Teacher() 19 | { 20 | this.Courses = new HashSet(); 21 | } 22 | 23 | public int TeacherId { get; set; } 24 | public string TeacherName { get; set; } 25 | public Nullable StandardId { get; set; } 26 | public Nullable TeacherType { get; set; } 27 | 28 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 29 | public virtual ICollection Courses { get; set; } 30 | public virtual Standard Standard { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/View_StudentCourse.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 EF6DBFirstDemo 11 | { 12 | using System; 13 | using System.Collections.Generic; 14 | 15 | public partial class View_StudentCourse 16 | { 17 | public int StudentID { get; set; } 18 | public string StudentName { get; set; } 19 | public int CourseId { get; set; } 20 | public string CourseName { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EF6DBFirstDemo/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Entity Framework Tutorial 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EF6-DBFirst-Demo 2 | Entity Framework 6 Database-First Demo Project 3 | 4 | Instructions to run this demo project: 5 | - Download EF6-DBFirst-Demo project and open it in Visual Studio 2017. 6 | - Open MS SQL Server 2012 and attach SchoolDB.mdf (included in EF6DBFirstDemo folder). 7 | - Verify the connection string in App.config in Visual Studio and make sure that it is pointing to your local DB server. 8 | --------------------------------------------------------------------------------