/// <summary> /// 访问 <see cref="SelectExpression"/>。 /// </summary> /// <param name="select">要访问的表达式。</param> /// <returns></returns> protected override Expression VisitSelect(SelectExpression select) { if (select.From != null && select.From.NodeType == (ExpressionType)DbExpressionType.Table) { var table = (TableExpression)select.From; //首先要找到具有假删除标记的列表达式 foreach (var column in select.Columns) { base.Visit(column.Expression); } if (fakeColumn != null && fakeColumn.Alias.Equals(table.Alias)) { var where = select.Where; var condExp = fakeColumn.Equal(Expression.Constant(0.ToType(fakeColumn.Type))); return(select.Update(select.From, where != null ? Expression.And(where, condExp) : condExp, select.OrderBy, select.GroupBy, select.Skip, select.Take, select.Segment, select.IsDistinct, select.Columns, select.Having, select.IsReverse)); } } else if (select.From != null) { var from = base.Visit(select.From); return(select.Update(from, select.Where, select.OrderBy, select.GroupBy, select.Skip, select.Take, select.Segment, select.IsDistinct, select.Columns, select.Having, select.IsReverse)); } return(select); }
public override ProjectionExpression GetQueryExpression(MappingEntity entity) { var tables = this.mapping.GetTables(entity); if (tables.Count <= 1) { return(base.GetQueryExpression(entity)); } var aliases = new Dictionary <string, TableAlias>(); MappingTable rootTable = tables.Single(ta => !this.mapping.IsExtensionTable(ta)); var tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(rootTable)); aliases.Add(this.mapping.GetAlias(rootTable), tex.Alias); Expression source = tex; foreach (MappingTable table in tables.Where(t => this.mapping.IsExtensionTable(t))) { TableAlias joinedTableAlias = new TableAlias(); string extensionAlias = this.mapping.GetAlias(table); aliases.Add(extensionAlias, joinedTableAlias); List <string> keyColumns = this.mapping.GetExtensionKeyColumnNames(table).ToList(); List <MemberInfo> relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToList(); string relatedAlias = this.mapping.GetExtensionRelatedAlias(table); TableAlias relatedTableAlias; aliases.TryGetValue(relatedAlias, out relatedTableAlias); TableExpression joinedTex = new TableExpression(joinedTableAlias, entity, this.mapping.GetTableName(table)); Expression cond = null; for (int i = 0, n = keyColumns.Count; i < n; i++) { var memberType = TypeHelper.GetMemberType(relatedMembers[i]); var colType = this.GetColumnType(entity, relatedMembers[i]); var relatedColumn = new ColumnExpression(memberType, colType, relatedTableAlias, this.mapping.GetColumnName(entity, relatedMembers[i])); var joinedColumn = new ColumnExpression(memberType, colType, joinedTableAlias, keyColumns[i]); var eq = joinedColumn.Equal(relatedColumn); cond = (cond != null) ? cond.And(eq) : eq; } source = new JoinExpression(JoinType.SingletonLeftOuter, source, joinedTex, cond); } var columns = new List <ColumnDeclaration>(); this.GetColumns(entity, aliases, columns); SelectExpression root = new SelectExpression(new TableAlias(), columns, source, null); var existingAliases = aliases.Values.ToArray(); Expression projector = this.GetEntityExpression(root, entity); var selectAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, root.Alias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, root, null), pc.Projector); return((ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType)); }
private Expression GetIdentityCheck(TableExpression root, MappingEntity entity, Expression instance, MappingTable table) { if (this.mapping.IsExtensionTable(table)) { var keyColNames = this.mapping.GetExtensionKeyColumnNames(table).ToArray(); var relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToArray(); Expression where = null; for (int i = 0, n = keyColNames.Length; i < n; i++) { var relatedMember = relatedMembers[i]; var cex = new ColumnExpression(TypeHelper.GetMemberType(relatedMember), this.GetColumnType(entity, relatedMember), root.Alias, keyColNames[n]); var nex = this.GetMemberExpression(instance, entity, relatedMember); var eq = cex.Equal(nex); where = (where != null) ? where.And(eq) : where; } return(where); } else { return(base.GetIdentityCheck(root, entity, instance)); } }
private Expression GetIdentityCheck(TableExpression root, MappingEntity entity, Expression instance, MappingTable table) { if (this.mapping.IsExtensionTable(table)) { var keyColNames = this.mapping.GetExtensionKeyColumnNames(table).ToArray(); var relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToArray(); Expression where = null; for (int i = 0, n = keyColNames.Length; i < n; i++) { var relatedMember = relatedMembers[i]; var cex = new ColumnExpression(TypeHelper.GetMemberType(relatedMember), this.GetColumnType(entity, relatedMember), root.Alias, keyColNames[n]); var nex = this.GetMemberExpression(instance, entity, relatedMember); var eq = cex.Equal(nex); where = (where != null) ? where.And(eq) : where; } return where; } else { return base.GetIdentityCheck(root, entity, instance); } }
public override ProjectionExpression GetQueryExpression(MappingEntity entity) { var tables = this.mapping.GetTables(entity); if (tables.Count <= 1) { return base.GetQueryExpression(entity); } var aliases = new Dictionary<string, TableAlias>(); MappingTable rootTable = tables.Single(ta => !this.mapping.IsExtensionTable(ta)); var tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(rootTable)); aliases.Add(this.mapping.GetAlias(rootTable), tex.Alias); Expression source = tex; foreach (MappingTable table in tables.Where(t => this.mapping.IsExtensionTable(t))) { TableAlias joinedTableAlias = new TableAlias(); string extensionAlias = this.mapping.GetAlias(table); aliases.Add(extensionAlias, joinedTableAlias); List<string> keyColumns = this.mapping.GetExtensionKeyColumnNames(table).ToList(); List<MemberInfo> relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToList(); string relatedAlias = this.mapping.GetExtensionRelatedAlias(table); TableAlias relatedTableAlias; aliases.TryGetValue(relatedAlias, out relatedTableAlias); TableExpression joinedTex = new TableExpression(joinedTableAlias, entity, this.mapping.GetTableName(table)); Expression cond = null; for (int i = 0, n = keyColumns.Count; i < n; i++) { var memberType = TypeHelper.GetMemberType(relatedMembers[i]); var colType = this.GetColumnType(entity, relatedMembers[i]); var relatedColumn = new ColumnExpression(memberType, colType, relatedTableAlias, this.mapping.GetColumnName(entity, relatedMembers[i])); var joinedColumn = new ColumnExpression(memberType, colType, joinedTableAlias, keyColumns[i]); var eq = joinedColumn.Equal(relatedColumn); cond = (cond != null) ? cond.And(eq) : eq; } source = new JoinExpression(JoinType.SingletonLeftOuter, source, joinedTex, cond); } var columns = new List<ColumnDeclaration>(); this.GetColumns(entity, aliases, columns); SelectExpression root = new SelectExpression(new TableAlias(), columns, source, null); var existingAliases = aliases.Values.ToArray(); Expression projector = this.GetEntityExpression(root, entity); var selectAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, root.Alias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, root, null), pc.Projector ); return (ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType); }
private Expression BindAnyAll(Expression source, MethodInfo method, LambdaExpression predicate, bool isRoot) { bool isAll = method.Name == "All"; ConstantExpression constSource = source as ConstantExpression; if (constSource != null && !IsQuery(constSource)) { System.Diagnostics.Debug.Assert(!isRoot); Expression where = null; foreach (object value in (IEnumerable)constSource.Value) { Expression expr = Expression.Invoke(predicate, Expression.Constant(value, predicate.Parameters[0].Type)); if (where == null) { where = expr; } else if (isAll) { where = where.And(expr); } else { where = where.Or(expr); } } return this.Visit(where); } else { if (isAll) { predicate = Expression.Lambda(Expression.Not(predicate.Body), predicate.Parameters.ToArray()); } if (predicate != null) { source = Expression.Call(typeof(Enumerable), "Where", method.GetGenericArguments(), source, predicate); } ProjectionExpression projection = this.VisitSequence(source); Expression result = new ExistsExpression(projection.Select); if (isAll) { result = Expression.Not(result); } if (isRoot) { if (this.language.AllowSubqueryInSelectWithoutFrom) { return GetSingletonSequence(result, "SingleOrDefault"); } else { // use count aggregate instead of exists var colType = this.language.TypeSystem.GetColumnType(typeof(int)); var newSelect = projection.Select.SetColumns( new[] { new ColumnDeclaration("value", new AggregateExpression(typeof(int), "Count", null, false), colType) } ); var colx = new ColumnExpression(typeof(int), colType, newSelect.Alias, "value"); var exp = isAll ? colx.Equal(Expression.Constant(0)) : colx.GreaterThan(Expression.Constant(0)); return new ProjectionExpression( newSelect, exp, Aggregator.GetAggregator(typeof(bool), typeof(IEnumerable<bool>)) ); } } return result; } }
protected override Expression GetInsertResult(MappingEntity entity, Expression instance, LambdaExpression selector, Dictionary<MemberInfo, Expression> map) { var tables = _mapping.GetTables(entity); if (tables.Count <= 1) { return base.GetInsertResult(entity, instance, selector, map); } var aliases = new Dictionary<string, TableAlias>(); MappingTable rootTable = tables.Single(ta => !_mapping.IsExtensionTable(ta)); var tableExpression = new TableExpression(new TableAlias(), entity, _mapping.GetTableName(rootTable)); var aggregator = Aggregator.GetAggregator(selector.Body.Type, typeof (IEnumerable<>).MakeGenericType(selector.Body.Type)); aliases.Add(_mapping.GetAlias(rootTable), tableExpression.Alias); Expression source = tableExpression; foreach (MappingTable table in tables.Where(t => _mapping.IsExtensionTable(t))) { TableAlias joinedTableAlias = new TableAlias(); string extensionAlias = _mapping.GetAlias(table); aliases.Add(extensionAlias, joinedTableAlias); List<string> keyColumns = _mapping.GetExtensionKeyColumnNames(table).ToList(); List<MemberInfo> relatedMembers = _mapping.GetExtensionRelatedMembers(table).ToList(); string relatedAlias = _mapping.GetExtensionRelatedAlias(table); TableAlias relatedTableAlias; aliases.TryGetValue(relatedAlias, out relatedTableAlias); TableExpression joinedTex = new TableExpression(joinedTableAlias, entity, _mapping.GetTableName(table)); Expression cond = null; for (int i = 0, n = keyColumns.Count; i < n; i++) { var memberType = TypeHelper.GetMemberType(relatedMembers[i]); var colType = GetColumnType(entity, relatedMembers[i]); var relatedColumn = new ColumnExpression(memberType, colType, relatedTableAlias, _mapping.GetColumnName(entity, relatedMembers[i])); var joinedColumn = new ColumnExpression(memberType, colType, joinedTableAlias, keyColumns[i]); var eq = joinedColumn.Equal(relatedColumn); cond = (cond != null) ? cond.And(eq) : eq; } source = new JoinExpression(JoinType.SingletonLeftOuter, source, joinedTex, cond); } Expression where; DeclarationCommand genIdCommand = null; var generatedIds = _mapping.GetMappedMembers(entity).Where( m => _mapping.IsPrimaryKey(entity, m) && _mapping.IsGenerated(entity, m)).ToList(); if (generatedIds.Count > 0) { if (map == null || !generatedIds.Any(m => map.ContainsKey(m))) { var localMap = new Dictionary<MemberInfo, Expression>(); genIdCommand = GetGeneratedIdCommand(entity, generatedIds.ToList(), localMap); map = localMap; } var mex = selector.Body as MemberExpression; if (mex != null && _mapping.IsPrimaryKey(entity, mex.Member) && _mapping.IsGenerated(entity, mex.Member)) { if (genIdCommand != null) { return new ProjectionExpression( genIdCommand.Source, new ColumnExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name), aggregator ); } TableAlias alias = new TableAlias(); var colType = GetColumnType(entity, mex.Member); return new ProjectionExpression( new SelectExpression(alias, new[] {new ColumnDeclaration("", map[mex.Member], colType)}, null, null), new ColumnExpression(TypeHelper.GetMemberType(mex.Member), colType, alias, ""), aggregator ); } where = generatedIds.Select((m, i) => GetMemberExpression(source, entity, m).Equal(map[m]) ).Aggregate((x, y) => x.And(y)); } else { where = GetIdentityCheck(tableExpression, entity, instance); } var columns = new List<ColumnDeclaration>(); GetColumns(entity, aliases, columns); SelectExpression root = new SelectExpression(new TableAlias(), columns, source, null); Expression typeProjector = GetEntityExpression(tableExpression, entity); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(Translator.Linguist.Language, selection, null, newAlias, tableExpression.Alias); var pe = new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, root, where), pc.Projector, aggregator ); if (genIdCommand != null) { return new BlockCommand(genIdCommand, pe); } return pe; }
private Expression BindAnyAll(Expression source, MethodInfo method, LambdaExpression predicate, bool isRoot) { bool isAll = method.Name.Equals("All", StringComparison.InvariantCultureIgnoreCase); ConstantExpression constSource = source as ConstantExpression; if (constSource != null && !IsQuery(constSource)) { System.Diagnostics.Debug.Assert(!isRoot); Expression where = null; foreach (object value in (IEnumerable)constSource.Value) { Expression expr = Expression.Invoke(predicate, Expression.Constant(value, predicate.Parameters[0].Type)); if (where == null) { where = expr; } else if (isAll) { where = where.And(expr); } else { where = where.Or(expr); } } return(this.Visit(where)); } else { if (isAll) { predicate = Expression.Lambda(Expression.Not(predicate.Body), predicate.Parameters.ToArray()); } if (predicate != null) { source = Expression.Call(typeof(Enumerable), "Where", method.GetGenericArguments(), source, predicate); } ProjectionExpression projection = this.VisitSequence(source); Expression result = new ExistsExpression(projection.Select); if (isAll) { result = Expression.Not(result); } if (isRoot) { if (this.language.AllowSubqueryInSelectWithoutFrom) { return(GetSingletonSequence(result, "SingleOrDefault")); } else { // use count aggregate instead of exists //var colType = this.language.TypeSystem.GetColumnType(typeof(int)); var newSelect = projection.Select.SetColumns(new[] { new ColumnDeclaration("value", new AggregateExpression(typeof(int), "Count", null, false)) }); var colx = new ColumnExpression(typeof(int), newSelect.Alias, "value"); var exp = isAll ? colx.Equal(Expression.Constant(0)) : colx.GreaterThan(Expression.Constant(0)); return(new ProjectionExpression(newSelect, exp, Aggregator.GetAggregator(typeof(bool), typeof(IEnumerable <bool>)))); } } return(result); } }