protected override Expression VisitProjection(SqlProjectionExpression projectionExpression) { if (typeof(RelatedDataAccessObjects <>).IsAssignableFromIgnoreGenericParameters(projectionExpression.Type)) { var elementType = projectionExpression.Type.GetGenericArguments()[0]; var originalPlaceholderCount = 0; var currentPlaceholderCount = originalPlaceholderCount; var replacedExpressions = new List <Expression>(); projectionExpression = (SqlProjectionExpression)SqlOuterQueryReferencePlaceholderSubstitutor.Substitute(projectionExpression, ref currentPlaceholderCount, replacedExpressions); var values = replacedExpressions.Select(c => Expression.Convert(this.Visit(c), typeof(object))).ToList(); var where = projectionExpression.Select.Where; var typeDescriptor = this.dataAccessModel.TypeDescriptorProvider.GetTypeDescriptor(elementType); var columns = QueryBinder.GetColumnInfos(this.dataAccessModel.TypeDescriptorProvider, typeDescriptor.PersistedProperties); var columnExpression = (SqlColumnExpression)SqlExpressionFinder.FindFirst(where, c => c.NodeType == (ExpressionType)SqlExpressionType.Column); var match = columns.Single(d => d.ColumnName == columnExpression.Name); var reference = Expression.Call(Expression.Constant(this.dataAccessModel), MethodInfoFastRef.DataAccessModelGetReferenceByValuesMethod.MakeGenericMethod(match.ForeignType.Type), Expression.NewArrayInit(typeof(object), values)); var property = typeDescriptor.GetRelationshipInfos().Single(c => c.ReferencingProperty == match.RootProperty).TargetProperty; return(Expression.Convert(Expression.Property(reference, property), this.dataAccessModel.GetConcreteTypeFromDefinitionType(property.PropertyType))); } else { var currentPlaceholderCount = 0; var replacedExpressions = new List <Expression>(); projectionExpression = (SqlProjectionExpression)SqlOuterQueryReferencePlaceholderSubstitutor.Substitute(projectionExpression, ref currentPlaceholderCount, replacedExpressions); var newColumnIndexes = projectionExpression.Select.Columns.Select((c, i) => new { c.Name, i }).ToDictionary(d => d.Name, d => d.i); var savedScope = this.scope; this.scope = new ProjectionBuilderScope(newColumnIndexes); var projectionProjector = Expression.Lambda(this.Visit(projectionExpression.Projector), objectProjector, dataReader, versionParameter, dynamicParameters); this.scope = savedScope; var values = replacedExpressions.Select(c => (Expression)Expression.Convert(Visit(c), typeof(object))).ToList(); var method = TypeUtils.GetMethod <SqlQueryProvider>(c => c.BuildExecution(default(SqlProjectionExpression), default(LambdaExpression), default(object[]))); MethodInfo evaluate; if (projectionExpression.Type.GetSequenceElementType() == null) { evaluate = MethodInfoFastRef.ExecutionBuildResultEvaluateMethod.MakeGenericMethod(projectionExpression.Type); } else { evaluate = MethodInfoFastRef.ExecutionBuildResultEvaluateMethod.MakeGenericMethod(typeof(IEnumerable <>).MakeGenericType(projectionExpression.Type.GetSequenceElementType())); } return(Expression.Call(Expression.Call(Expression.Property(this.objectProjector, "QueryProvider"), method, Expression.Constant(projectionExpression), projectionProjector, Expression.NewArrayInit(typeof(object), values)), evaluate)); } }
private ProjectionBuilder(DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryProvider queryProvider, ProjectionBuilderScope scope) { this.dataAccessModel = dataAccessModel; this.sqlDatabaseContext = sqlDatabaseContext; this.queryProvider = queryProvider; this.scope = scope; this.dataReader = Expression.Parameter(typeof(IDataReader), "dataReader"); this.objectProjector = Expression.Parameter(typeof(ObjectProjector), "objectProjector"); this.dynamicParameters = Expression.Parameter(typeof(object[]), "dynamicParameters"); this.versionParameter = Expression.Parameter(typeof(int), "version"); }
private ProjectionBuilder(DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryProvider queryProvider, ProjectionBuilderScope scope) { this.dataAccessModel = dataAccessModel; this.sqlDatabaseContext = sqlDatabaseContext; this.queryProvider = queryProvider; this.scope = scope; this.dataReader = Expression.Parameter(typeof(IDataReader), "dataReader"); this.objectProjector = Expression.Parameter(typeof(ObjectProjector), "objectProjector"); this.dynamicParameters = Expression.Parameter(typeof (object[]), "dynamicParameters"); this.versionParameter = Expression.Parameter(typeof(int), "version"); this.filterParameter = Expression.Parameter(typeof(Func<DataAccessObject, DataAccessObject>), "filter"); }
public static LambdaExpression Build(DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryProvider queryProvider, Expression expression, ProjectionBuilderScope scope, out Expression<Func<IDataReader, object[]>> rootKeys) { var projectionBuilder = new ProjectionBuilder(dataAccessModel, sqlDatabaseContext, queryProvider, scope); var body = projectionBuilder.Visit(expression); if (projectionBuilder.scope.rootPrimaryKeys.Count > 0) { rootKeys = Expression.Lambda<Func<IDataReader, object[]>>(Expression.NewArrayInit(typeof(object), projectionBuilder.scope.rootPrimaryKeys), projectionBuilder.dataReader); } else { rootKeys = null; } return Expression.Lambda(body, projectionBuilder.objectProjector, projectionBuilder.dataReader, projectionBuilder.versionParameter, projectionBuilder.dynamicParameters, projectionBuilder.filterParameter); }
public static LambdaExpression Build(DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryProvider queryProvider, Expression expression, ProjectionBuilderScope scope) { var projectionBuilder = new ProjectionBuilder(dataAccessModel, sqlDatabaseContext, queryProvider, scope); var body = projectionBuilder.Visit(expression); return(Expression.Lambda(body, projectionBuilder.objectProjector, projectionBuilder.dataReader, projectionBuilder.versionParameter, projectionBuilder.dynamicParameters)); }
public static LambdaExpression Build(DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryProvider queryProvider, Expression expression, ProjectionBuilderScope scope, out Expression <Func <IDataReader, object[]> > rootKeys) { var projectionBuilder = new ProjectionBuilder(dataAccessModel, sqlDatabaseContext, queryProvider, scope); var body = projectionBuilder.Visit(expression); if (projectionBuilder.scope.rootPrimaryKeys.Count > 0) { rootKeys = Expression.Lambda <Func <IDataReader, object[]> >(Expression.NewArrayInit(typeof(object), projectionBuilder.scope.rootPrimaryKeys), projectionBuilder.dataReader); } else { rootKeys = null; } return(Expression.Lambda(typeof(ObjectReaderFunc <>).MakeGenericType(body.Type), body, projectionBuilder.objectProjector, projectionBuilder.dataReader, projectionBuilder.versionParameter, projectionBuilder.dynamicParameters)); }
protected override Expression VisitProjection(SqlProjectionExpression projectionExpression) { if (typeof(RelatedDataAccessObjects<>).IsAssignableFromIgnoreGenericParameters(projectionExpression.Type)) { var elementType = projectionExpression.Type.GetGenericArguments()[0]; var originalPlaceholderCount = 0; var currentPlaceholderCount = originalPlaceholderCount; var replacedExpressions = new List<Expression>(); projectionExpression = (SqlProjectionExpression)SqlOuterQueryReferencePlaceholderSubstitutor.Substitute(projectionExpression, ref currentPlaceholderCount, replacedExpressions); var values = replacedExpressions.Select(c => Expression.Convert(this.Visit(c), typeof(object))).ToList(); var where = projectionExpression.Select.Where; var typeDescriptor = this.dataAccessModel.TypeDescriptorProvider.GetTypeDescriptor(elementType); var columns = QueryBinder.GetColumnInfos(this.dataAccessModel.TypeDescriptorProvider, typeDescriptor.PersistedProperties); var columnExpression = (SqlColumnExpression)SqlExpressionFinder.FindFirst(where, c => c.NodeType == (ExpressionType)SqlExpressionType.Column); var match = columns.Single(d => d.ColumnName == columnExpression.Name); var reference = Expression.Call(Expression.Constant(this.dataAccessModel), MethodInfoFastRef.DataAccessModelGetReferenceByValuesMethod.MakeGenericMethod(match.ForeignType.Type), Expression.NewArrayInit(typeof(object), values)); var property = typeDescriptor.GetRelationshipInfos().Single(c => c.ReferencingProperty == match.RootProperty).TargetProperty; return Expression.Convert(Expression.Property(reference, property), this.dataAccessModel.GetConcreteTypeFromDefinitionType(property.PropertyType)); } else { var currentPlaceholderCount = 0; var replacedExpressions = new List<Expression>(); projectionExpression = (SqlProjectionExpression)SqlOuterQueryReferencePlaceholderSubstitutor.Substitute(projectionExpression, ref currentPlaceholderCount, replacedExpressions); var newColumnIndexes = projectionExpression.Select.Columns.Select((c, i) => new { c.Name, i }).ToDictionary(d => d.Name, d => d.i); var savedScope = this.scope; this.scope = new ProjectionBuilderScope(newColumnIndexes); var projectionProjector = Expression.Lambda(this.Visit(projectionExpression.Projector), objectProjector, dataReader, versionParameter, dynamicParameters, filterParameter); Expression rootKeys; if (this.scope.rootPrimaryKeys.Count > 0) { rootKeys = Expression.Quote(Expression.Lambda<Func<IDataReader, object[]>>(Expression.NewArrayInit(typeof(object), this.scope.rootPrimaryKeys), this.dataReader)); } else { rootKeys = Expression.Constant(null, typeof(Expression<Func<IDataReader, object[]>>)); } this.scope = savedScope; var values = replacedExpressions.Select(c => (Expression)Expression.Convert(Visit(c), typeof(object))).ToList(); var method = TypeUtils.GetMethod<SqlQueryProvider>(c => c.BuildExecution(default(SqlProjectionExpression), default(LambdaExpression), default(object[]), default(Expression<Func<IDataReader, object[]>>))); MethodInfo evaluate; if (projectionExpression.Type.GetSequenceElementType() == null) { evaluate = MethodInfoFastRef.ExecutionBuildResultEvaluateMethod.MakeGenericMethod(projectionExpression.Type); } else { evaluate = MethodInfoFastRef.ExecutionBuildResultEvaluateMethod.MakeGenericMethod(typeof(IEnumerable<>).MakeGenericType(projectionExpression.Type.GetSequenceElementType())); } return Expression.Call(Expression.Call(Expression.Property(this.objectProjector, "QueryProvider"), method, Expression.Constant(SqlAggregateProjectionNormalizer.Normalize(projectionExpression)), projectionProjector, Expression.NewArrayInit(typeof(object), values), rootKeys), evaluate); } }