DatabaseModel.Context.tt 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. <#@ template language="C#" debug="false" hostspecific="true"#>
  2. <#@ include file="EF6.Utility.CS.ttinclude"#><#@
  3. output extension=".cs"#><#
  4. const string inputFile = @"DatabaseModel.edmx";
  5. var textTransform = DynamicTextTransformation.Create(this);
  6. var code = new CodeGenerationTools(this);
  7. var ef = new MetadataTools(this);
  8. var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
  9. var loader = new EdmMetadataLoader(textTransform.Host, textTransform.Errors);
  10. var itemCollection = loader.CreateEdmItemCollection(inputFile);
  11. var modelNamespace = loader.GetModelNamespace(inputFile);
  12. var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
  13. var container = itemCollection.OfType<EntityContainer>().FirstOrDefault();
  14. if (container == null)
  15. {
  16. return string.Empty;
  17. }
  18. #>
  19. //------------------------------------------------------------------------------
  20. // <auto-generated>
  21. // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#>
  22. //
  23. // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#>
  24. // <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#>
  25. // </auto-generated>
  26. //------------------------------------------------------------------------------
  27. <#
  28. var codeNamespace = code.VsNamespaceSuggestion();
  29. if (!String.IsNullOrEmpty(codeNamespace))
  30. {
  31. #>
  32. namespace <#=code.EscapeNamespace(codeNamespace)#>
  33. {
  34. <#
  35. PushIndent(" ");
  36. }
  37. #>
  38. using System;
  39. using System.Data.Entity;
  40. using System.Data.Entity.Infrastructure;
  41. <#
  42. if (container.FunctionImports.Any())
  43. {
  44. #>
  45. using System.Data.Entity.Core.Objects;
  46. using System.Linq;
  47. <#
  48. }
  49. #>
  50. <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
  51. {
  52. public <#=code.Escape(container)#>()
  53. : base("name=<#=container.Name#>")
  54. {
  55. <#
  56. if (!loader.IsLazyLoadingEnabled(container))
  57. {
  58. #>
  59. this.Configuration.LazyLoadingEnabled = false;
  60. <#
  61. }
  62. foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
  63. {
  64. // Note: the DbSet members are defined below such that the getter and
  65. // setter always have the same accessibility as the DbSet definition
  66. if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
  67. {
  68. #>
  69. <#=codeStringGenerator.DbSetInitializer(entitySet)#>
  70. <#
  71. }
  72. }
  73. #>
  74. }
  75. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  76. {
  77. throw new UnintentionalCodeFirstException();
  78. }
  79. <#
  80. foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
  81. {
  82. #>
  83. <#=codeStringGenerator.DbSet(entitySet)#>
  84. <#
  85. }
  86. foreach (var edmFunction in container.FunctionImports)
  87. {
  88. WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false);
  89. }
  90. #>
  91. }
  92. <#
  93. if (!String.IsNullOrEmpty(codeNamespace))
  94. {
  95. PopIndent();
  96. #>
  97. }
  98. <#
  99. }
  100. #>
  101. <#+
  102. private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
  103. {
  104. if (typeMapper.IsComposable(edmFunction))
  105. {
  106. #>
  107. [DbFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")]
  108. <#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#>
  109. {
  110. <#+
  111. codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter);
  112. #>
  113. <#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#>
  114. }
  115. <#+
  116. }
  117. else
  118. {
  119. #>
  120. <#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#>
  121. {
  122. <#+
  123. codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter);
  124. #>
  125. <#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#>
  126. }
  127. <#+
  128. if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption))
  129. {
  130. WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true);
  131. }
  132. }
  133. }
  134. public void WriteFunctionParameter(string name, string isNotNull, string notNullInit, string nullInit)
  135. {
  136. #>
  137. var <#=name#> = <#=isNotNull#> ?
  138. <#=notNullInit#> :
  139. <#=nullInit#>;
  140. <#+
  141. }
  142. public const string TemplateId = "CSharp_DbContext_Context_EF6";
  143. public class CodeStringGenerator
  144. {
  145. private readonly CodeGenerationTools _code;
  146. private readonly TypeMapper _typeMapper;
  147. private readonly MetadataTools _ef;
  148. public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
  149. {
  150. ArgumentNotNull(code, "code");
  151. ArgumentNotNull(typeMapper, "typeMapper");
  152. ArgumentNotNull(ef, "ef");
  153. _code = code;
  154. _typeMapper = typeMapper;
  155. _ef = ef;
  156. }
  157. public string Property(EdmProperty edmProperty)
  158. {
  159. return string.Format(
  160. CultureInfo.InvariantCulture,
  161. "{0} {1} {2} {{ {3}get; {4}set; }}",
  162. Accessibility.ForProperty(edmProperty),
  163. _typeMapper.GetTypeName(edmProperty.TypeUsage),
  164. _code.Escape(edmProperty),
  165. _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
  166. _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
  167. }
  168. public string NavigationProperty(NavigationProperty navProp)
  169. {
  170. var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
  171. return string.Format(
  172. CultureInfo.InvariantCulture,
  173. "{0} {1} {2} {{ {3}get; {4}set; }}",
  174. AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
  175. navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
  176. _code.Escape(navProp),
  177. _code.SpaceAfter(Accessibility.ForGetter(navProp)),
  178. _code.SpaceAfter(Accessibility.ForSetter(navProp)));
  179. }
  180. public string AccessibilityAndVirtual(string accessibility)
  181. {
  182. return accessibility + (accessibility != "private" ? " virtual" : "");
  183. }
  184. public string EntityClassOpening(EntityType entity)
  185. {
  186. return string.Format(
  187. CultureInfo.InvariantCulture,
  188. "{0} {1}partial class {2}{3}",
  189. Accessibility.ForType(entity),
  190. _code.SpaceAfter(_code.AbstractOption(entity)),
  191. _code.Escape(entity),
  192. _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
  193. }
  194. public string EnumOpening(SimpleType enumType)
  195. {
  196. return string.Format(
  197. CultureInfo.InvariantCulture,
  198. "{0} enum {1} : {2}",
  199. Accessibility.ForType(enumType),
  200. _code.Escape(enumType),
  201. _code.Escape(_typeMapper.UnderlyingClrType(enumType)));
  202. }
  203. public void WriteFunctionParameters(EdmFunction edmFunction, Action<string, string, string, string> writeParameter)
  204. {
  205. var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
  206. foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
  207. {
  208. var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
  209. var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")";
  210. var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))";
  211. writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
  212. }
  213. }
  214. public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
  215. {
  216. var parameters = _typeMapper.GetParameters(edmFunction);
  217. return string.Format(
  218. CultureInfo.InvariantCulture,
  219. "{0} IQueryable<{1}> {2}({3})",
  220. AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
  221. _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
  222. _code.Escape(edmFunction),
  223. string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()));
  224. }
  225. public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
  226. {
  227. var parameters = _typeMapper.GetParameters(edmFunction);
  228. return string.Format(
  229. CultureInfo.InvariantCulture,
  230. "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
  231. _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
  232. edmFunction.NamespaceName,
  233. edmFunction.Name,
  234. string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
  235. _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
  236. }
  237. public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
  238. {
  239. var parameters = _typeMapper.GetParameters(edmFunction);
  240. var returnType = _typeMapper.GetReturnType(edmFunction);
  241. var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray());
  242. if (includeMergeOption)
  243. {
  244. paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
  245. }
  246. return string.Format(
  247. CultureInfo.InvariantCulture,
  248. "{0} {1} {2}({3})",
  249. AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
  250. returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
  251. _code.Escape(edmFunction),
  252. paramList);
  253. }
  254. public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
  255. {
  256. var parameters = _typeMapper.GetParameters(edmFunction);
  257. var returnType = _typeMapper.GetReturnType(edmFunction);
  258. var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
  259. if (includeMergeOption)
  260. {
  261. callParams = ", mergeOption" + callParams;
  262. }
  263. return string.Format(
  264. CultureInfo.InvariantCulture,
  265. "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});",
  266. returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
  267. edmFunction.Name,
  268. callParams);
  269. }
  270. public string DbSet(EntitySet entitySet)
  271. {
  272. return string.Format(
  273. CultureInfo.InvariantCulture,
  274. "{0} virtual DbSet<{1}> {2} {{ get; set; }}",
  275. Accessibility.ForReadOnlyProperty(entitySet),
  276. _typeMapper.GetTypeName(entitySet.ElementType),
  277. _code.Escape(entitySet));
  278. }
  279. public string DbSetInitializer(EntitySet entitySet)
  280. {
  281. return string.Format(
  282. CultureInfo.InvariantCulture,
  283. "{0} = Set<{1}>();",
  284. _code.Escape(entitySet),
  285. _typeMapper.GetTypeName(entitySet.ElementType));
  286. }
  287. public string UsingDirectives(bool inHeader, bool includeCollections = true)
  288. {
  289. return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
  290. ? string.Format(
  291. CultureInfo.InvariantCulture,
  292. "{0}using System;{1}" +
  293. "{2}",
  294. inHeader ? Environment.NewLine : "",
  295. includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
  296. inHeader ? "" : Environment.NewLine)
  297. : "";
  298. }
  299. }
  300. public class TypeMapper
  301. {
  302. private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
  303. private readonly System.Collections.IList _errors;
  304. private readonly CodeGenerationTools _code;
  305. private readonly MetadataTools _ef;
  306. public static string FixNamespaces(string typeName)
  307. {
  308. return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial.");
  309. }
  310. public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
  311. {
  312. ArgumentNotNull(code, "code");
  313. ArgumentNotNull(ef, "ef");
  314. ArgumentNotNull(errors, "errors");
  315. _code = code;
  316. _ef = ef;
  317. _errors = errors;
  318. }
  319. public string GetTypeName(TypeUsage typeUsage)
  320. {
  321. return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
  322. }
  323. public string GetTypeName(EdmType edmType)
  324. {
  325. return GetTypeName(edmType, isNullable: null, modelNamespace: null);
  326. }
  327. public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
  328. {
  329. return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
  330. }
  331. public string GetTypeName(EdmType edmType, string modelNamespace)
  332. {
  333. return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
  334. }
  335. public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
  336. {
  337. if (edmType == null)
  338. {
  339. return null;
  340. }
  341. var collectionType = edmType as CollectionType;
  342. if (collectionType != null)
  343. {
  344. return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
  345. }
  346. var typeName = _code.Escape(edmType.MetadataProperties
  347. .Where(p => p.Name == ExternalTypeNameAttributeName)
  348. .Select(p => (string)p.Value)
  349. .FirstOrDefault())
  350. ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
  351. _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
  352. _code.Escape(edmType));
  353. if (edmType is StructuralType)
  354. {
  355. return typeName;
  356. }
  357. if (edmType is SimpleType)
  358. {
  359. var clrType = UnderlyingClrType(edmType);
  360. if (!IsEnumType(edmType))
  361. {
  362. typeName = _code.Escape(clrType);
  363. }
  364. typeName = FixNamespaces(typeName);
  365. return clrType.IsValueType && isNullable == true ?
  366. String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :
  367. typeName;
  368. }
  369. throw new ArgumentException("edmType");
  370. }
  371. public Type UnderlyingClrType(EdmType edmType)
  372. {
  373. ArgumentNotNull(edmType, "edmType");
  374. var primitiveType = edmType as PrimitiveType;
  375. if (primitiveType != null)
  376. {
  377. return primitiveType.ClrEquivalentType;
  378. }
  379. if (IsEnumType(edmType))
  380. {
  381. return GetEnumUnderlyingType(edmType).ClrEquivalentType;
  382. }
  383. return typeof(object);
  384. }
  385. public object GetEnumMemberValue(MetadataItem enumMember)
  386. {
  387. ArgumentNotNull(enumMember, "enumMember");
  388. var valueProperty = enumMember.GetType().GetProperty("Value");
  389. return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
  390. }
  391. public string GetEnumMemberName(MetadataItem enumMember)
  392. {
  393. ArgumentNotNull(enumMember, "enumMember");
  394. var nameProperty = enumMember.GetType().GetProperty("Name");
  395. return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null);
  396. }
  397. public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
  398. {
  399. ArgumentNotNull(enumType, "enumType");
  400. var membersProperty = enumType.GetType().GetProperty("Members");
  401. return membersProperty != null
  402. ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null)
  403. : Enumerable.Empty<MetadataItem>();
  404. }
  405. public bool EnumIsFlags(EdmType enumType)
  406. {
  407. ArgumentNotNull(enumType, "enumType");
  408. var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
  409. return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null);
  410. }
  411. public bool IsEnumType(GlobalItem edmType)
  412. {
  413. ArgumentNotNull(edmType, "edmType");
  414. return edmType.GetType().Name == "EnumType";
  415. }
  416. public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
  417. {
  418. ArgumentNotNull(enumType, "enumType");
  419. return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
  420. }
  421. public string CreateLiteral(object value)
  422. {
  423. if (value == null || value.GetType() != typeof(TimeSpan))
  424. {
  425. return _code.CreateLiteral(value);
  426. }
  427. return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks);
  428. }
  429. public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable<string> types, string sourceFile)
  430. {
  431. ArgumentNotNull(types, "types");
  432. ArgumentNotNull(sourceFile, "sourceFile");
  433. var hash = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
  434. if (types.Any(item => !hash.Add(item)))
  435. {
  436. _errors.Add(
  437. new CompilerError(sourceFile, -1, -1, "6023",
  438. String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict"))));
  439. return false;
  440. }
  441. return true;
  442. }
  443. public IEnumerable<SimpleType> GetEnumItemsToGenerate(IEnumerable<GlobalItem> itemCollection)
  444. {
  445. return GetItemsToGenerate<SimpleType>(itemCollection)
  446. .Where(e => IsEnumType(e));
  447. }
  448. public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T: EdmType
  449. {
  450. return itemCollection
  451. .OfType<T>()
  452. .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
  453. .OrderBy(i => i.Name);
  454. }
  455. public IEnumerable<string> GetAllGlobalItems(IEnumerable<GlobalItem> itemCollection)
  456. {
  457. return itemCollection
  458. .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
  459. .Select(g => GetGlobalItemName(g));
  460. }
  461. public string GetGlobalItemName(GlobalItem item)
  462. {
  463. if (item is EdmType)
  464. {
  465. return ((EdmType)item).Name;
  466. }
  467. else
  468. {
  469. return ((EntityContainer)item).Name;
  470. }
  471. }
  472. public IEnumerable<EdmProperty> GetSimpleProperties(EntityType type)
  473. {
  474. return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
  475. }
  476. public IEnumerable<EdmProperty> GetSimpleProperties(ComplexType type)
  477. {
  478. return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
  479. }
  480. public IEnumerable<EdmProperty> GetComplexProperties(EntityType type)
  481. {
  482. return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
  483. }
  484. public IEnumerable<EdmProperty> GetComplexProperties(ComplexType type)
  485. {
  486. return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
  487. }
  488. public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(EntityType type)
  489. {
  490. return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
  491. }
  492. public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(ComplexType type)
  493. {
  494. return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
  495. }
  496. public IEnumerable<NavigationProperty> GetNavigationProperties(EntityType type)
  497. {
  498. return type.NavigationProperties.Where(np => np.DeclaringType == type);
  499. }
  500. public IEnumerable<NavigationProperty> GetCollectionNavigationProperties(EntityType type)
  501. {
  502. return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
  503. }
  504. public FunctionParameter GetReturnParameter(EdmFunction edmFunction)
  505. {
  506. ArgumentNotNull(edmFunction, "edmFunction");
  507. var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters");
  508. return returnParamsProperty == null
  509. ? edmFunction.ReturnParameter
  510. : ((IEnumerable<FunctionParameter>)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault();
  511. }
  512. public bool IsComposable(EdmFunction edmFunction)
  513. {
  514. ArgumentNotNull(edmFunction, "edmFunction");
  515. var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute");
  516. return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null);
  517. }
  518. public IEnumerable<FunctionImportParameter> GetParameters(EdmFunction edmFunction)
  519. {
  520. return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
  521. }
  522. public TypeUsage GetReturnType(EdmFunction edmFunction)
  523. {
  524. var returnParam = GetReturnParameter(edmFunction);
  525. return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage);
  526. }
  527. public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption)
  528. {
  529. var returnType = GetReturnType(edmFunction);
  530. return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
  531. }
  532. }
  533. public static void ArgumentNotNull<T>(T arg, string name) where T : class
  534. {
  535. if (arg == null)
  536. {
  537. throw new ArgumentNullException(name);
  538. }
  539. }
  540. #>