|
| 1 | +<# // Sample Oracle T4 template to customize mapping all database numeric column types to .NET properties. The mapped .NET properties store a superset of values of their mapped database types. #> |
| 2 | + |
| 3 | +<#@ template hostSpecific="true" #> |
| 4 | +<#@ assembly name="Microsoft.EntityFrameworkCore" #> |
| 5 | +<#@ assembly name="Microsoft.EntityFrameworkCore.Design" #> |
| 6 | +<#@ assembly name="Microsoft.EntityFrameworkCore.Relational" #> |
| 7 | +<#@ assembly name="Microsoft.Extensions.DependencyInjection.Abstractions" #> |
| 8 | +<#@ parameter name="EntityType" type="Microsoft.EntityFrameworkCore.Metadata.IEntityType" #> |
| 9 | +<#@ parameter name="Options" type="Microsoft.EntityFrameworkCore.Scaffolding.ModelCodeGenerationOptions" #> |
| 10 | +<#@ parameter name="NamespaceHint" type="System.String" #> |
| 11 | +<#@ import namespace="System.Collections.Generic" #> |
| 12 | +<#@ import namespace="System.ComponentModel.DataAnnotations" #> |
| 13 | +<#@ import namespace="System.Linq" #> |
| 14 | +<#@ import namespace="System.Text" #> |
| 15 | +<#@ import namespace="Microsoft.EntityFrameworkCore" #> |
| 16 | +<#@ import namespace="Microsoft.EntityFrameworkCore.Design" #> |
| 17 | +<#@ import namespace="Microsoft.Extensions.DependencyInjection" #> |
| 18 | +<# |
| 19 | + if (EntityType.IsSimpleManyToManyJoinEntityType()) |
| 20 | + { |
| 21 | + // Don't scaffold these |
| 22 | + return ""; |
| 23 | + } |
| 24 | + |
| 25 | + var services = (IServiceProvider)Host; |
| 26 | + var annotationCodeGenerator = services.GetRequiredService<IAnnotationCodeGenerator>(); |
| 27 | + var code = services.GetRequiredService<ICSharpHelper>(); |
| 28 | + |
| 29 | + var usings = new List<string> |
| 30 | + { |
| 31 | + "System", |
| 32 | + "System.Collections.Generic" |
| 33 | + }; |
| 34 | + |
| 35 | + if (Options.UseDataAnnotations) |
| 36 | + { |
| 37 | + usings.Add("System.ComponentModel.DataAnnotations"); |
| 38 | + usings.Add("System.ComponentModel.DataAnnotations.Schema"); |
| 39 | + usings.Add("Microsoft.EntityFrameworkCore"); |
| 40 | + } |
| 41 | + |
| 42 | + if (!string.IsNullOrEmpty(NamespaceHint)) |
| 43 | + { |
| 44 | +#> |
| 45 | +namespace <#= NamespaceHint #>; |
| 46 | + |
| 47 | +<# |
| 48 | + } |
| 49 | + |
| 50 | + if (!string.IsNullOrEmpty(EntityType.GetComment())) |
| 51 | + { |
| 52 | +#> |
| 53 | +/// <summary> |
| 54 | +/// <#= code.XmlComment(EntityType.GetComment()) #> |
| 55 | +/// </summary> |
| 56 | +<# |
| 57 | + } |
| 58 | + |
| 59 | + if (Options.UseDataAnnotations) |
| 60 | + { |
| 61 | + foreach (var dataAnnotation in EntityType.GetDataAnnotations(annotationCodeGenerator)) |
| 62 | + { |
| 63 | +#> |
| 64 | +<#= code.Fragment(dataAnnotation) #> |
| 65 | +<# |
| 66 | + } |
| 67 | + } |
| 68 | +#> |
| 69 | +public partial class <#= EntityType.Name #> |
| 70 | +{ |
| 71 | +<# |
| 72 | + var firstProperty = true; |
| 73 | + foreach (var property in EntityType.GetProperties().OrderBy(p => p.GetColumnOrder() ?? -1)) |
| 74 | + { |
| 75 | + if (!firstProperty) |
| 76 | + { |
| 77 | + WriteLine(""); |
| 78 | + } |
| 79 | + |
| 80 | + if (!string.IsNullOrEmpty(property.GetComment())) |
| 81 | + { |
| 82 | +#> |
| 83 | + /// <summary> |
| 84 | + /// <#= code.XmlComment(property.GetComment(), indent: 1) #> |
| 85 | + /// </summary> |
| 86 | +<# |
| 87 | + } |
| 88 | + |
| 89 | + if (Options.UseDataAnnotations) |
| 90 | + { |
| 91 | + var dataAnnotations = property.GetDataAnnotations(annotationCodeGenerator) |
| 92 | + .Where(a => !(a.Type == typeof(RequiredAttribute) && Options.UseNullableReferenceTypes && !property.ClrType.IsValueType)); |
| 93 | + foreach (var dataAnnotation in dataAnnotations) |
| 94 | + { |
| 95 | +#> |
| 96 | + <#= code.Fragment(dataAnnotation) #> |
| 97 | +<# |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + // Make changes here to customize type mapping for all properties of certain column types. |
| 102 | + Type clrType; |
| 103 | + string columnType = property.GetColumnType(); // Get the store type for which we want custom mapping. |
| 104 | + |
| 105 | + if (columnType == "NUMBER(1)") |
| 106 | + { |
| 107 | + clrType = Options.UseNullableReferenceTypes && property.IsNullable ? typeof(byte?) : typeof(byte); // Map NUMBER(1) to byte. |
| 108 | + } |
| 109 | + else if (columnType == "NUMBER(2)" || columnType == "NUMBER(3)" || columnType == "NUMBER(4)") |
| 110 | + { |
| 111 | + clrType = Options.UseNullableReferenceTypes && property.IsNullable ? typeof(Int16?) : typeof(Int16); // Map NUMBER(2) to NUMBER(4) to Int16. |
| 112 | + } |
| 113 | + else if (columnType == "NUMBER(5)") |
| 114 | + { |
| 115 | + clrType = Options.UseNullableReferenceTypes && property.IsNullable ? typeof(Int32?) : typeof(Int32); // Map NUMBER(5) to Int32. |
| 116 | + } |
| 117 | + else if (columnType == "NUMBER(6)" || columnType == "NUMBER(7)" || columnType == "NUMBER(8)" || |
| 118 | + columnType == "NUMBER(9)" || columnType == "NUMBER(10)") |
| 119 | + { |
| 120 | + clrType = Options.UseNullableReferenceTypes && property.IsNullable ? typeof(Int64?) : typeof(Int64); // Map NUMBER(6) to NUMBER(10) to Int64. |
| 121 | + } |
| 122 | + else if (columnType == "NUMBER(11)" || columnType == "NUMBER(12)" || columnType == "NUMBER(13)" || |
| 123 | + columnType == "NUMBER(14)" || columnType == "NUMBER(15)" || columnType == "NUMBER(16)" || |
| 124 | + columnType == "NUMBER(17)" || columnType == "NUMBER(18)" || columnType == "NUMBER(19)") |
| 125 | + { |
| 126 | + clrType = Options.UseNullableReferenceTypes && property.IsNullable ? typeof(Decimal?) : typeof(Decimal); // Map NUMBER(11) to NUMBER(19) to Decimal. |
| 127 | + } |
| 128 | + // Add more column types as required. |
| 129 | + else |
| 130 | + { |
| 131 | + clrType = property.ClrType; // Keep the default CLR Type. |
| 132 | + } |
| 133 | + |
| 134 | + |
| 135 | + usings.AddRange(code.GetRequiredUsings(clrType)); |
| 136 | + |
| 137 | + var needsNullable = Options.UseNullableReferenceTypes && property.IsNullable && !clrType.IsValueType; |
| 138 | + var needsInitializer = Options.UseNullableReferenceTypes && !property.IsNullable && !clrType.IsValueType; |
| 139 | +#> |
| 140 | + public <#= code.Reference(clrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #> |
| 141 | +<# |
| 142 | + firstProperty = false; |
| 143 | + } |
| 144 | + |
| 145 | + foreach (var navigation in EntityType.GetNavigations()) |
| 146 | + { |
| 147 | + WriteLine(""); |
| 148 | + |
| 149 | + if (Options.UseDataAnnotations) |
| 150 | + { |
| 151 | + foreach (var dataAnnotation in navigation.GetDataAnnotations(annotationCodeGenerator)) |
| 152 | + { |
| 153 | +#> |
| 154 | + <#= code.Fragment(dataAnnotation) #> |
| 155 | +<# |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + var targetType = navigation.TargetEntityType.Name; |
| 160 | + if (navigation.IsCollection) |
| 161 | + { |
| 162 | +#> |
| 163 | + public virtual ICollection<<#= targetType #>> <#= navigation.Name #> { get; set; } = new List<<#= targetType #>>(); |
| 164 | +<# |
| 165 | + } |
| 166 | + else |
| 167 | + { |
| 168 | + var needsNullable = Options.UseNullableReferenceTypes && !(navigation.ForeignKey.IsRequired && navigation.IsOnDependent); |
| 169 | + var needsInitializer = Options.UseNullableReferenceTypes && navigation.ForeignKey.IsRequired && navigation.IsOnDependent; |
| 170 | +#> |
| 171 | + public virtual <#= targetType #><#= needsNullable ? "?" : "" #> <#= navigation.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #> |
| 172 | +<# |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + foreach (var skipNavigation in EntityType.GetSkipNavigations()) |
| 177 | + { |
| 178 | + WriteLine(""); |
| 179 | + |
| 180 | + if (Options.UseDataAnnotations) |
| 181 | + { |
| 182 | + foreach (var dataAnnotation in skipNavigation.GetDataAnnotations(annotationCodeGenerator)) |
| 183 | + { |
| 184 | +#> |
| 185 | + <#= code.Fragment(dataAnnotation) #> |
| 186 | +<# |
| 187 | + } |
| 188 | + } |
| 189 | +#> |
| 190 | + public virtual ICollection<<#= skipNavigation.TargetEntityType.Name #>> <#= skipNavigation.Name #> { get; set; } = new List<<#= skipNavigation.TargetEntityType.Name #>>(); |
| 191 | +<# |
| 192 | + } |
| 193 | +#> |
| 194 | +} |
| 195 | +<# |
| 196 | + var previousOutput = GenerationEnvironment; |
| 197 | + GenerationEnvironment = new StringBuilder(); |
| 198 | + |
| 199 | + foreach (var ns in usings.Distinct().OrderBy(x => x, new NamespaceComparer())) |
| 200 | + { |
| 201 | +#> |
| 202 | +using <#= ns #>; |
| 203 | +<# |
| 204 | + } |
| 205 | + |
| 206 | + WriteLine(""); |
| 207 | + |
| 208 | + GenerationEnvironment.Append(previousOutput); |
| 209 | +#> |
0 commit comments