EMIS.Entities.tt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. <#@ template language="C#" debug="false" hostspecific="true"#>
  2. <#@ include file="EF.Utility.CS.ttinclude"#><#@
  3. output extension=".cs"#><#
  4. CodeGenerationTools code = new CodeGenerationTools(this);
  5. MetadataLoader loader = new MetadataLoader(this);
  6. CodeRegion region = new CodeRegion(this, 1);
  7. MetadataTools ef = new MetadataTools(this);
  8. string inputFile = @"EMISContext.edmx";
  9. EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
  10. string namespaceName = code.VsNamespaceSuggestion();
  11. EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
  12. WriteHeader(fileManager);
  13. string summary=string.Empty;
  14. foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
  15. {
  16. fileManager.StartNewFile(entity.Name + ".cs");
  17. BeginNamespace(namespaceName, code);
  18. if(entity.Documentation !=null && entity.Documentation.Summary!=null)
  19. summary=entity.Documentation.Summary;
  20. else
  21. summary=entity.Name;
  22. #>
  23. #pragma warning disable 1573
  24. using System;
  25. using System.Collections.Generic;
  26. /// <summary>
  27. /// <#=summary#>
  28. /// </summary>
  29. <#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#>
  30. {
  31. <#
  32. var propertiesWithDefaultValues = entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity && p.DefaultValue != null);
  33. var collectionNavigationProperties = entity.NavigationProperties.Where(np => np.DeclaringType == entity && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
  34. var complexProperties = entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity);
  35. var dupPropertyTypes = entity.NavigationProperties.GroupBy(x => code.Escape(x.ToEndMember.GetEntityType())).Where(x => x.Count() > 1).Select(x => x.Key).ToList();
  36. if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
  37. {
  38. #>
  39. public <#=code.Escape(entity)#>()
  40. {
  41. <#
  42. foreach (var edmProperty in propertiesWithDefaultValues)
  43. {
  44. #>
  45. this.<#=code.Escape(edmProperty)#> = <#=code.CreateLiteral(edmProperty.DefaultValue)#>;
  46. <#
  47. }
  48. foreach (var navigationProperty in collectionNavigationProperties)
  49. {
  50. if (dupPropertyTypes.Contains(code.Escape(navigationProperty.ToEndMember.GetEntityType())))
  51. {
  52. #>
  53. this.<#=navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ?
  54. (((AssociationType)navigationProperty.RelationshipType).IsForeignKey ?
  55. code.Escape(code.Escape(navigationProperty.ToEndMember.GetEntityType()) + "_" + GetRelationPropertyName(navigationProperty, loader, inputFile))
  56. : code.Escape(((AssociationType)navigationProperty.RelationshipType).Name)
  57. )
  58. : code.Escape(GetRelationPropertyName(navigationProperty, loader, inputFile) + "_Nav")#> = new HashSet<<#=code.Escape(navigationProperty.ToEndMember.GetEntityType())#>>();
  59. <#
  60. }
  61. else
  62. {
  63. #>
  64. this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=code.Escape(navigationProperty.ToEndMember.GetEntityType())#>>();
  65. <#
  66. }
  67. }
  68. foreach (var complexProperty in complexProperties)
  69. {
  70. #>
  71. this.<#=code.Escape(complexProperty)#> = new <#=code.Escape(complexProperty.TypeUsage)#>();
  72. <#
  73. }
  74. #>
  75. }
  76. <#
  77. }
  78. var primitiveProperties = entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity);
  79. if (primitiveProperties.Any())
  80. {
  81. foreach (var edmProperty in primitiveProperties)
  82. {
  83. WriteProperty(code, edmProperty);
  84. }
  85. }
  86. if (complexProperties.Any())
  87. {
  88. #>
  89. <#
  90. foreach(var complexProperty in complexProperties)
  91. {
  92. WriteProperty(code, complexProperty);
  93. }
  94. }
  95. var navigationProperties = entity.NavigationProperties.Where(np => np.DeclaringType == entity);
  96. if (navigationProperties.Any())
  97. {
  98. #>
  99. <#
  100. foreach (var navigationProperty in navigationProperties)
  101. {
  102. if (dupPropertyTypes.Contains(code.Escape(navigationProperty.ToEndMember.GetEntityType())))
  103. {
  104. WriteNavigationPropertyByName(code, navigationProperty, loader, inputFile);
  105. }
  106. else
  107. {
  108. WriteNavigationProperty(code, navigationProperty);
  109. }
  110. }
  111. }
  112. #>
  113. }
  114. <#
  115. EndNamespace(namespaceName);
  116. }
  117. foreach (var complex in ItemCollection.GetItems<ComplexType>().OrderBy(e => e.Name))
  118. {
  119. fileManager.StartNewFile(complex.Name + ".cs");
  120. BeginNamespace(namespaceName, code);
  121. #>
  122. using System;
  123. <#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#>
  124. {
  125. <#
  126. var complexProperties = complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex);
  127. var propertiesWithDefaultValues = complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex && p.DefaultValue != null);
  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)#> = <#=code.CreateLiteral(edmProperty.DefaultValue)#>;
  138. <#
  139. }
  140. foreach (var complexProperty in complexProperties)
  141. {
  142. #>
  143. this.<#=code.Escape(complexProperty)#> = new <#=code.Escape(complexProperty.TypeUsage)#>();
  144. <#
  145. }
  146. #>
  147. }
  148. <#
  149. }
  150. var primitiveProperties = complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex);
  151. if (primitiveProperties.Any())
  152. {
  153. foreach(var edmProperty in primitiveProperties)
  154. {
  155. WriteProperty(code, edmProperty);
  156. }
  157. }
  158. if (complexProperties.Any())
  159. {
  160. #>
  161. <#
  162. foreach(var edmProperty in complexProperties)
  163. {
  164. WriteProperty(code, edmProperty);
  165. }
  166. }
  167. #>
  168. }
  169. <#
  170. EndNamespace(namespaceName);
  171. }
  172. if (!VerifyTypesAreCaseInsensitiveUnique(ItemCollection))
  173. {
  174. return "";
  175. }
  176. fileManager.Process();
  177. #>
  178. <#+
  179. void WriteHeader(EntityFrameworkTemplateFileManager fileManager)
  180. {
  181. fileManager.StartHeader();
  182. #>
  183. //------------------------------------------------------------------------------
  184. // <auto-generated>
  185. // This code was generated from a template.
  186. //
  187. // Manual changes to this file may cause unexpected behavior in your application.
  188. // Manual changes to this file will be overwritten if the code is regenerated.
  189. // </auto-generated>
  190. //------------------------------------------------------------------------------
  191. <#+
  192. fileManager.EndBlock();
  193. }
  194. void BeginNamespace(string namespaceName, CodeGenerationTools code)
  195. {
  196. CodeRegion region = new CodeRegion(this);
  197. if (!String.IsNullOrEmpty(namespaceName))
  198. {
  199. #>
  200. namespace <#=code.EscapeNamespace(namespaceName)#>
  201. {
  202. <#+
  203. PushIndent(CodeRegion.GetIndent(1));
  204. }
  205. }
  206. void EndNamespace(string namespaceName)
  207. {
  208. if (!String.IsNullOrEmpty(namespaceName))
  209. {
  210. PopIndent();
  211. #>
  212. }
  213. <#+
  214. }
  215. }
  216. string GetRelationPropertyName(NavigationProperty relationProperty, MetadataLoader loader, string inputFile)
  217. {
  218. if (((AssociationType)relationProperty.RelationshipType).IsForeignKey)
  219. {
  220. MetadataWorkspace metadataWorkspace = null;
  221. bool allMetadataLoaded =loader.TryLoadAllMetadata(inputFile, out metadataWorkspace);
  222. var association = metadataWorkspace
  223. .GetItems<AssociationType>(DataSpace.SSpace)
  224. .Single(a => a.Name == relationProperty.RelationshipType.Name);
  225. return string.Join("_", association.ReferentialConstraints.SelectMany(rc => rc.ToProperties));
  226. }
  227. else
  228. {
  229. return relationProperty.Name;
  230. }
  231. }
  232. void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
  233. {
  234. if (edmProperty.Documentation != null && edmProperty.Documentation.Summary != null)
  235. {
  236. WriteProperty(Accessibility.ForProperty(edmProperty),
  237. code.Escape(edmProperty.Documentation.Summary),
  238. code.Escape(edmProperty.TypeUsage),
  239. code.Escape(edmProperty),
  240. code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
  241. code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
  242. }
  243. else
  244. {
  245. WriteProperty(Accessibility.ForProperty(edmProperty),
  246. code.Escape(edmProperty.Name),
  247. code.Escape(edmProperty.TypeUsage),
  248. code.Escape(edmProperty),
  249. code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
  250. code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
  251. }
  252. }
  253. void WriteNavigationProperty(CodeGenerationTools code, NavigationProperty navigationProperty)
  254. {
  255. var endType = code.Escape(navigationProperty.ToEndMember.GetEntityType());
  256. if (navigationProperty.Documentation != null && navigationProperty.Documentation.Summary != null)
  257. {
  258. WriteProperty(PropertyVirtualModifier(Accessibility.ForProperty(navigationProperty)),
  259. code.Escape(navigationProperty.Documentation.Summary),
  260. navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("HashSet<" + endType + ">") : endType,
  261. code.Escape(navigationProperty),
  262. code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
  263. code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
  264. }
  265. else
  266. {
  267. WriteProperty(PropertyVirtualModifier(Accessibility.ForProperty(navigationProperty)),
  268. code.Escape(navigationProperty.Name),
  269. navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("HashSet<" + endType + ">") : endType,
  270. code.Escape(navigationProperty),
  271. code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
  272. code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
  273. }
  274. }
  275. void WriteNavigationPropertyByName(CodeGenerationTools code, NavigationProperty navigationProperty, MetadataLoader loader, string inputFile)
  276. {
  277. var endType = code.Escape(navigationProperty.ToEndMember.GetEntityType());
  278. if (navigationProperty.Documentation != null && navigationProperty.Documentation.Summary != null)
  279. {
  280. WriteProperty(PropertyVirtualModifier(Accessibility.ForProperty(navigationProperty)),
  281. code.Escape(navigationProperty.Documentation.Summary),
  282. navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("HashSet<" + endType + ">") : endType,
  283. navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ?
  284. (((AssociationType)navigationProperty.RelationshipType).IsForeignKey ?
  285. code.Escape(code.Escape(navigationProperty.ToEndMember.GetEntityType()) + "_" + GetRelationPropertyName(navigationProperty, loader, inputFile))
  286. : code.Escape(((AssociationType)navigationProperty.RelationshipType).Name)
  287. )
  288. : code.Escape(GetRelationPropertyName(navigationProperty, loader, inputFile) + "_Nav"),
  289. code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
  290. code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
  291. }
  292. else
  293. {
  294. WriteProperty(PropertyVirtualModifier(Accessibility.ForProperty(navigationProperty)),
  295. code.Escape(navigationProperty.Name),
  296. navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("HashSet<" + endType + ">") : endType,
  297. navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ?
  298. (((AssociationType)navigationProperty.RelationshipType).IsForeignKey ?
  299. code.Escape(code.Escape(navigationProperty.ToEndMember.GetEntityType()) + "_" + GetRelationPropertyName(navigationProperty, loader, inputFile))
  300. : code.Escape(((AssociationType)navigationProperty.RelationshipType).Name)
  301. )
  302. : code.Escape(GetRelationPropertyName(navigationProperty, loader, inputFile) + "_Nav"),
  303. code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
  304. code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
  305. }
  306. }
  307. void WriteProperty(string accessibility, string summary, string type, string name, string getterAccessibility, string setterAccessibility)
  308. {
  309. #>
  310. /// <summary>
  311. /// <#=summary#>
  312. /// </summary>
  313. <#=accessibility#> <#=type#> <#=name#> { <#=getterAccessibility#>get; <#=setterAccessibility#>set; }
  314. <#+
  315. }
  316. string PropertyVirtualModifier(string accessibility)
  317. {
  318. return accessibility + (accessibility != "private" ? " virtual" : "");
  319. }
  320. bool VerifyTypesAreCaseInsensitiveUnique(EdmItemCollection itemCollection)
  321. {
  322. var alreadySeen = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
  323. foreach(var type in itemCollection.GetItems<StructuralType>())
  324. {
  325. if (!(type is EntityType || type is ComplexType))
  326. {
  327. continue;
  328. }
  329. if (alreadySeen.ContainsKey(type.FullName))
  330. {
  331. Error(String.Format(CultureInfo.CurrentCulture, "This template does not support types that differ only by case, the types {0} are not supported", type.FullName));
  332. return false;
  333. }
  334. else
  335. {
  336. alreadySeen.Add(type.FullName, true);
  337. }
  338. }
  339. return true;
  340. }
  341. #>