private static EdmType CreateResultType(DbModel model, ResultDescriptor result) { EdmType edmType = GetSimpleEdmType(model, result.Type); if (edmType == null) { edmType = GetStructuralEdmType(model, result.Type); } if (edmType == null) { throw new InvalidOperationException(string.Format("Edm type is not found for result type {0}.", result.Type.FullName)); } switch (edmType.BuiltInTypeKind) { case BuiltInTypeKind.EntityType: var propertyMappings = ((EntityType)edmType).Properties.Join( model.ConceptualToStoreMapping.EntitySetMappings .SelectMany(t => t.EntityTypeMappings) .Where(t => edmType.Yield(e => e.BaseType, (e, b) => b, e => e != null).Contains(t.EntityType)) .SelectMany(tm => tm.Fragments.SelectMany(t => t.PropertyMappings)) .OfType <ScalarPropertyMapping>(), p => p, pm => pm.Property, (p, pm) => new { Property = p, TypeUsage = TypeUsage.Create(pm.Column.TypeUsage.EdmType, pm.Column.TypeUsage.Facets.Where(f => !new[] { "StoreGeneratedPattern", "ConcurrencyMode" }.Contains(f.Name))) }); return(RowType.Create(propertyMappings.Select(pm => EdmProperty.Create(pm.Property.Name, pm.TypeUsage)), null)); case BuiltInTypeKind.ComplexType: return(RowType.Create(((StructuralType)edmType).Members.Select(m => { string columnName = null; MetadataProperty metadata; //if (!m.MetadataProperties.TryGetValue("Configuration", true, out metadata) || !metadata.Value.TryGetProperty("ColumnName", out columnName)) if (m.MetadataProperties.TryGetValue("ClrAttributes", true, out metadata)) { var columnAttr = ((IEnumerable)m.MetadataProperties["ClrAttributes"].Value).OfType <ColumnAttribute>().SingleOrDefault(); if (columnAttr != null && !string.IsNullOrEmpty(columnAttr.Name)) { columnName = columnAttr.Name; } } return EdmProperty.Create(columnName ?? m.Name, model.ProviderManifest.GetStoreType(m.TypeUsage)); }), null)); case BuiltInTypeKind.EnumType: return(RowType.Create(new[] { EdmProperty.CreateEnum(result.ColumnName, (EnumType)edmType) }, null)); case BuiltInTypeKind.PrimitiveType: return(RowType.Create(new[] { EdmProperty.CreatePrimitive(result.ColumnName, (PrimitiveType)edmType) }, null)); default: throw new NotSupportedException(); } }
private FunctionDescriptor BuildFunctionDescriptor(MethodInfo mi) { DbFunctionAttribute attrFunction = mi.GetCustomAttribute <DbFunctionAttribute>(); if (attrFunction == null) { throw new InvalidOperationException(string.Format("Method {0} of type {1} must be marked by'DbFunction...' attribute.", mi.Name, mi.DeclaringType)); } DbFunctionExAttribute attrFunctionEx = attrFunction as DbFunctionExAttribute; string methodName = mi.Name; string functionName = !string.IsNullOrWhiteSpace(attrFunction.FunctionName) ? attrFunction.FunctionName : methodName; string databaseSchema = attrFunctionEx != null && !string.IsNullOrWhiteSpace(attrFunctionEx.Schema) ? attrFunctionEx.Schema : _databaseSchema; if (string.IsNullOrWhiteSpace(databaseSchema)) { throw new InvalidOperationException(string.Format("Database schema for method {0} of type {1} is not defined.", mi.Name, mi.DeclaringType)); } // bool isExtension = mi.IsDefined(typeof(ExtensionAttribute), false); ParameterDescriptor[] parameters = mi.GetParameters() .SkipWhile(pi => isExtension && pi.Position == 0 && pi.ParameterType.IsAssignableFrom(typeof(DbContext))) .OrderBy(pi => pi.Position) .Select((pi, i) => { FunctionParameterAttribute parameterAttr = pi.GetCustomAttribute <FunctionParameterAttribute>(); Type parameterType = pi.ParameterType == typeof(ObjectParameter) ? parameterAttr.Type : pi.ParameterType; if (parameterType == null) { throw new InvalidOperationException(string.Format("Method parameter '{0}' at position {1} is not defined.", pi.Name, pi.Position)); } // MinLengthAttribute minLengthAttr = pi.GetCustomAttribute <MinLengthAttribute>(); MaxLengthAttribute maxLengthAttr = pi.GetCustomAttribute <MaxLengthAttribute>(); FixedLengthAttribute fixedLengthAttr = pi.GetCustomAttribute <FixedLengthAttribute>(); PrecisionScaleAttribute precisionScaleAttr = pi.GetCustomAttribute <PrecisionScaleAttribute>(); // return(new ParameterDescriptor(i, parameterType.IsByRef ? pi.IsOut ? ParameterDirection.Output : ParameterDirection.InputOutput : ParameterDirection.Input, parameterType) { Name = parameterAttr != null && !string.IsNullOrWhiteSpace(parameterAttr.Name) ? parameterAttr.Name : pi.Name, StoreTypeName = parameterAttr != null && !string.IsNullOrWhiteSpace(parameterAttr.TypeName) ? parameterAttr.TypeName : null, Length = maxLengthAttr != null ? maxLengthAttr.Length : default(int?), IsFixedLength = minLengthAttr != null && maxLengthAttr != null ? minLengthAttr.Length == maxLengthAttr.Length : fixedLengthAttr != null ? fixedLengthAttr.IsFixedLength : default(bool?), Precision = precisionScaleAttr != null ? precisionScaleAttr.Precision : default(byte?), Scale = precisionScaleAttr != null ? precisionScaleAttr.Scale : default(byte?) }); }) .ToArray(); // IQueryable<> Type returnType = mi.ReturnType.IsGenericType && mi.ReturnType.GetGenericTypeDefinition() == typeof(IQueryable <>) ? mi.ReturnType : mi.ReturnType.GetInterfaces().SingleOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IQueryable <>)); if (returnType != null) { FunctionResultAttribute attrResult = mi.ReturnParameter.GetCustomAttribute <FunctionResultAttribute>(); ResultDescriptor result = new ResultDescriptor(returnType.GetGenericArguments()[0]) { ColumnName = attrResult != null ? attrResult.ColumnName : _resultColumnName, StoreTypeName = attrResult != null ? attrResult.TypeName : null }; return(new FunctionDescriptor(_namespaceName, databaseSchema, functionName, true, attrFunctionEx != null ? attrFunctionEx.IsComposable : default(bool?), isExtension ? attrFunctionEx != null ? attrFunctionEx.IsBuiltIn : default(bool?) : false, false, parameters.Length == 0 ? attrFunctionEx != null ? attrFunctionEx.IsNiladic : default(bool?) : false, attrFunctionEx != null ? attrFunctionEx.ParameterTypeSemantics : default(ParameterTypeSemantics?), parameters, Enumerable.Repeat(result, 1))); } // IQueryable returnType = mi.ReturnType == typeof(IQueryable) ? mi.ReturnType : mi.ReturnType.GetInterfaces().SingleOrDefault(t => t == typeof(IQueryable)); if (returnType != null) { FunctionResultAttribute attrResult = mi.ReturnParameter.GetCustomAttribute <FunctionResultAttribute>(); if (attrResult != null) { ResultDescriptor result = new ResultDescriptor(attrResult.Type) { ColumnName = attrResult.ColumnName ?? _resultColumnName, StoreTypeName = attrResult.TypeName }; return(new FunctionDescriptor(_namespaceName, databaseSchema, functionName, true, attrFunctionEx != null ? attrFunctionEx.IsComposable : default(bool?), isExtension ? attrFunctionEx != null ? attrFunctionEx.IsBuiltIn : default(bool?) : false, false, parameters.Length == 0 ? attrFunctionEx != null ? attrFunctionEx.IsNiladic : default(bool?) : false, attrFunctionEx != null ? attrFunctionEx.ParameterTypeSemantics : default(ParameterTypeSemantics?), parameters, Enumerable.Repeat(result, 1))); } throw new InvalidOperationException("Result type is not specified in function"); } // IEnumerable<> returnType = mi.ReturnType == typeof(string) || mi.ReturnType == typeof(byte[]) ? null : mi.ReturnType.IsGenericType && mi.ReturnType.GetGenericTypeDefinition() == typeof(IEnumerable <>) ? mi.ReturnType : mi.ReturnType.GetInterfaces().SingleOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable <>)); if (returnType != null) { FunctionResultAttribute attrResult = mi.ReturnParameter.GetCustomAttribute <FunctionResultAttribute>(); IEnumerable <ResultDescriptor> results = Enumerable.Repeat(new ResultDescriptor(returnType.GetGenericArguments()[0]) { ColumnName = attrResult != null ? attrResult.ColumnName : _resultColumnName, StoreTypeName = attrResult != null ? attrResult.TypeName : null }, 1) .Concat(mi.GetCustomAttributes <FunctionResultAttribute>() .Select(a => new ResultDescriptor(a.Type) { ColumnName = a.ColumnName ?? _resultColumnName, StoreTypeName = a.TypeName })); return(new FunctionDescriptor(_namespaceName, databaseSchema, functionName, true, false, false, false, parameters.Length == 0 ? attrFunctionEx != null ? attrFunctionEx.IsNiladic : default(bool?) : false, attrFunctionEx != null ? attrFunctionEx.ParameterTypeSemantics : default(ParameterTypeSemantics?), parameters, results)); } // IEnumerable returnType = mi.ReturnType == typeof(string) || mi.ReturnType == typeof(byte[]) ? null : mi.ReturnType == typeof(IEnumerable) ? mi.ReturnType : mi.ReturnType.GetInterfaces().SingleOrDefault(t => t == typeof(IEnumerable)); if (returnType != null) { IEnumerable <ResultDescriptor> results = mi.GetCustomAttributes <FunctionResultAttribute>() .Select(a => new ResultDescriptor(a.Type) { ColumnName = a.ColumnName ?? _resultColumnName, StoreTypeName = a.TypeName }); return(new FunctionDescriptor(_namespaceName, databaseSchema, functionName, true, false, false, false, parameters.Length == 0 ? attrFunctionEx != null ? attrFunctionEx.IsNiladic : default(bool?) : false, attrFunctionEx != null ? attrFunctionEx.ParameterTypeSemantics : default(ParameterTypeSemantics?), parameters, results)); } // Scalar result returnType = mi.ReturnType; FunctionResultAttribute attr = mi.ReturnParameter.GetCustomAttribute <FunctionResultAttribute>(); ResultDescriptor resultDescriptor = new ResultDescriptor(mi.ReturnType) { StoreTypeName = attr != null ? attr.TypeName : null }; return(new FunctionDescriptor(_namespaceName, databaseSchema, functionName, false, attrFunctionEx != null ? attrFunctionEx.IsComposable : default(bool?), isExtension ? attrFunctionEx != null ? attrFunctionEx.IsBuiltIn : default(bool?) : false, attrFunctionEx != null ? attrFunctionEx.IsAggregate : default(bool?), parameters.Length == 0 ? attrFunctionEx != null ? attrFunctionEx.IsNiladic : default(bool?) : false, attrFunctionEx != null ? attrFunctionEx.ParameterTypeSemantics : default(ParameterTypeSemantics?), parameters, Enumerable.Repeat(resultDescriptor, 1))); }