├── .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 |
--------------------------------------------------------------------------------