根据Entity Framework6.X 数据生成代码(仅获取表名)

时间:2023-03-08 22:22:05
根据Entity Framework6.X 数据生成代码(仅获取表名)

近来学习ASP.NET MVC ,一直在看韩迎龙(Kencery)ASP.NET MVC+EF框架+EasyUI实现权限管理。在第九节(TT模板的学习)卡住了,作者使用EF5.0做数据源,而我使用的EF6.0,在代码生成时引用的ttinclude包不一样。EF5使用的是EF.Utility.CS.ttinclude,而EF6使用的是EF6.Utility.CS.ttinclude,两者部分代码完全不一样,使用方法也有很大区别,博客园,度娘,谷歌,都找了,找不到一篇关于EF6.Utility.CS.ttinclude这个文件的使用或内容介绍的文章,无奈只得自己摸索,无意间发现.edmx文件的添加代码生成项生成的文件接近我要生成的代码,所以借用此代码并修改成我想要的代码.不太理解,仅代码贴上,以供以后使用.(本篇获取表名,并将所有表名生成在一个文件中)。

这是设置部分(里面的const string inputFile = @"..\\DataModel\\DataModel.edmx"; 部分需要改成自己的数据源.

Code Snippet
  1. <#@ template language="C#" debug="false" hostspecific="true"#>
  2. <#@ include file="EF6.Utility.CS.ttinclude"#><#@ output extension=".cs"#>
  3.   <#const string inputFile = @"..\\DataModel\\DataModel.edmx";
  4.     var textTransform = DynamicTextTransformation.Create(this);
  5.     var code = new CodeGenerationTools(this);
  6.     var ef = new MetadataTools(this);
  7.     var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
  8.     var loader = new EdmMetadataLoader(textTransform.Host, textTransform.Errors);
  9.     var itemCollection = loader.CreateEdmItemCollection(inputFile);
  10.     var modelNamespace = loader.GetModelNamespace(inputFile);
  11.     var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
  12.     var container = itemCollection.OfType<EntityContainer>().FirstOrDefault();
  13.     if (container == null)
  14.     {
  15.         return string.Empty;
  16.     }#>

 

这是要生成的部分,建议先写好一个完整代码,然后在内部替换.一定要注意里面的各种符号的配对!!!!

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. //new using
  7. using IDAL;
  8. using System.Data.Common;
  9. <#
  10. var codeNamespace = code.VsNamespaceSuggestion();
  11. if (!String.IsNullOrEmpty(codeNamespace))
  12. {
  13. #>
  14. namespace <#=code.EscapeNamespace(codeNamespace)#>
  15. {
  16. <#
  17.     PushIndent("    ");
  18. }
  19. #>
  20. public partial interface IDBSession
  21. {
  22.     //
  23. <#
  24.     foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
  25.     {
  26. #>
  27.     /// <summary>
  28.     /// <#=entitySet #>
  29.     /// </summary>
  30.     <#="I"+entitySet+"Repository "+entitySet+"Repository { get; }" #>
  31. <#
  32.     }
  33. #>
  34.     //
  35.     int SaveChanges( );
  36.     int ExcuteSql( string strSql, DbParameter[] parameters );
  37. }
  38. <#
  39. if (!String.IsNullOrEmpty(codeNamespace))
  40. {
  41.     PopIndent();
  42. #>
  43. }
  44. <#
  45. }
  46. #>

 

下面这一部分完全是不需要改变的,这是生成代码使用的方法,属性,字段等,直接贴上来.

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