-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathEntity.tt
188 lines (168 loc) · 7.08 KB
/
Entity.tt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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
179
180
181
182
183
184
185
186
187
188
<#@ template hostspecific="true" language="C#" #>
<#@ include file="EF.Utility.CS.ttinclude" #><#@
output extension=".cs" #><#
var efHost = (EfTextTemplateHost)Host;
var code = new CodeGenerationTools(this);
#>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
<#
if (efHost.EntityFrameworkVersion >= new Version(4, 4))
{
WriteLine("using System.ComponentModel.DataAnnotations.Schema;");
}
#>
namespace <#= code.EscapeNamespace(efHost.Namespace) #>
{
<#
var tableName = (string)efHost.TableSet.MetadataProperties["Table"].Value ?? efHost.TableSet.Name;
var conventionTableName = System.Data.Entity.Design.PluralizationServices.PluralizationService
.CreateService(new CultureInfo("en"))
.Pluralize(efHost.EntityType.Name);
var schemaName = (string)efHost.TableSet.MetadataProperties["Schema"].Value;
schemaName = string.IsNullOrWhiteSpace(schemaName)
? "dbo"
: schemaName;
if(conventionTableName != tableName || schemaName != "dbo")
{
#>
[Table("<#= tableName #>", Schema="<#= schemaName #>")]
<#
}
#>
public partial class <#= efHost.EntityType.Name #>
{
<#
var collectionNavigations = efHost.EntityType.NavigationProperties.Where(
np => np.DeclaringType == efHost.EntityType
&& np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
// Add a ctor to initialize any collections
if (collectionNavigations.Any())
{
#>
public <#= code.Escape(efHost.EntityType) #>()
{
<#
foreach (var navProperty in collectionNavigations)
{
#>
this.<#= code.Escape(navProperty) #> = new List<<#= code.Escape(navProperty.ToEndMember.GetEntityType()) #>>();
<#
}
#>
}
<#
}
foreach (var property in efHost.EntityType.Properties)
{
var storeProp = efHost.PropertyToColumnMappings[property];
var sgpFacet = storeProp.TypeUsage.Facets.SingleOrDefault(f => f.Name == "StoreGeneratedPattern");
var columnName = efHost.PropertyToColumnMappings[property].Name;
var storeGeneratedPattern = sgpFacet == null ? StoreGeneratedPattern.None : (StoreGeneratedPattern)sgpFacet.Value;
var type = (PrimitiveType)property.TypeUsage.EdmType;
var fixedLengthFacet = (Facet)property.TypeUsage.Facets.SingleOrDefault(f => f.Name == "FixedLength");
var maxLengthFacet = (Facet)property.TypeUsage.Facets.SingleOrDefault(f => f.Name == "MaxLength");
var attributes = new List<string>();
// WRT the primary key, a given column can be:
// 1) part of the primary key, primary key is a single column
// 2) part of the primary key, primary key is multiple columns
// 3) not part of the primary key
// In addition, the column may separately need to have the column name specified due to the
// convention name not matching. This leads to 6 possible combinations that must be dealt
// with together, since the 'Column' attribute is used for both specifying column name and
// column ordering for multi-column primary keys.
var columnNameShouldBeSpecified = code.Escape(property) != columnName;
var isPartOfPrimaryKey = efHost.EntityType.KeyMembers.Contains(property);
var primaryKeyHasMultipleColumns = efHost.EntityType.KeyMembers.Count > 1;
if (isPartOfPrimaryKey)
{
if (primaryKeyHasMultipleColumns)
{
var columnNumber = efHost.EntityType.KeyMembers.IndexOf(property);
if (columnNameShouldBeSpecified)
{
attributes.Add(String.Format("[Key, Column(\"{0}\", Order = {1})]", columnName, columnNumber));
}
else
{
attributes.Add(String.Format("[Key, Column(Order = {0})]", columnNumber));
}
}
else
{
attributes.Add("[Key]");
}
}
else if (columnNameShouldBeSpecified)
{
// not part of primary key, so we can just emit the single column attribute if needed
attributes.Add(String.Format("[Column(\"{0}\")]", columnName));
}
// logic based on EF Power Tools Beta2 Mapping.tt
if (type.ClrEquivalentType == typeof(string)
|| type.ClrEquivalentType == typeof(byte[]))
{
if (!property.Nullable && storeGeneratedPattern == StoreGeneratedPattern.None)
{
attributes.Add("[Required]");
}
if (maxLengthFacet != null && !maxLengthFacet.IsUnbounded)
{
attributes.Add(String.Format("[MaxLength({0})]", maxLengthFacet.Value));
if (fixedLengthFacet != null && (bool)fixedLengthFacet.Value) //If IsFixed then MinLength = MaxLength
{
attributes.Add(String.Format("[MinLength({0})]", maxLengthFacet.Value));
}
if (storeGeneratedPattern == StoreGeneratedPattern.Computed
&& type.ClrEquivalentType == typeof(byte[])
&& (int)maxLengthFacet.Value == 8)
{
attributes.Add("[Timestamp]");
}
}
}
// logic based on EF Power Tools Beta2 Mapping.tt
var conventionStoreGeneratedPattern = StoreGeneratedPattern.None;
if (isPartOfPrimaryKey && primaryKeyHasMultipleColumns == false)
{
if (type.ClrEquivalentType == typeof(int)
|| type.ClrEquivalentType == typeof(decimal)
|| type.ClrEquivalentType == typeof(short)
|| type.ClrEquivalentType == typeof(long))
{
conventionStoreGeneratedPattern = StoreGeneratedPattern.Identity;
}
}
if (storeGeneratedPattern != conventionStoreGeneratedPattern)
{
attributes.Add(String.Format("[DatabaseGenerated(DatabaseGeneratedOption.{0})]", storeGeneratedPattern));
}
PushIndent(new string(' ', 8));
foreach (var attribute in attributes)
{
WriteLine(attribute);
}
ClearIndent();
#>
<#= Accessibility.ForProperty(property) #> <#= code.Escape(property.TypeUsage) #> <#= code.Escape(property) #> { get; set; }
<#
}
foreach (var navProperty in efHost.EntityType.NavigationProperties.Where(np => np.DeclaringType == efHost.EntityType))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
public virtual ICollection<<#= code.Escape(navProperty.ToEndMember.GetEntityType()) #>> <#= code.Escape(navProperty) #> { get; set; }
<#
}
else
{
#>
public virtual <#= code.Escape(navProperty.ToEndMember.GetEntityType()) #> <#= code.Escape(navProperty) #> { get; set; }
<#
}
}
#>
}
}