コード例 #1
0
        protected virtual IExpression VisitTable(TableIdentifier table)
        {
            if (table.IsTemporary)
            {
                _output.Append(table.Name);
            }
            else
            {
                _output.Append(this.GetIdentifier(table.Name));
            }

            if (!string.IsNullOrEmpty(table.Alias) && !string.Equals(table.Name, table.Alias))
            {
                _output.Append(" AS " + table.Alias);
            }

            return(table);
        }
コード例 #2
0
		public static ISource From(this IStatement statement, TableIdentifier origin, string memberPath, Func<ISource, IDataEntityComplexProperty, ISource> subqueryFactory, out IDataEntityProperty property)
		{
			var found = origin.Reduce(memberPath, ctx =>
			{
				var source = ctx.Source;

				if(ctx.Ancestors != null)
				{
					foreach(var ancestor in ctx.Ancestors)
					{
						source = statement.Join(source, ancestor, ctx.Path);
					}
				}

				if(ctx.Property.IsComplex)
				{
					var complex = (IDataEntityComplexProperty)ctx.Property;

					if(complex.Multiplicity == DataAssociationMultiplicity.Many)
					{
						if(subqueryFactory != null)
							return subqueryFactory(source, complex);

						//如果不允许一对多的子查询则抛出异常
						throw new DataException($"The specified '{ctx.FullPath}' member is a one-to-many composite(navigation) property that cannot appear in the sorting and specific condition clauses.");
					}

					source = statement.Join(source, complex, ctx.FullPath);
				}

				return source;
			});

			if(found.IsFailed)
				throw new DataException($"The specified '{memberPath}' member does not exist in the '{origin.Entity?.Name}' entity and it's inherits.");

			//输出找到的属性元素
			property = found.Property;

			//返回找到的源
			return found.Source;
		}
コード例 #3
0
        private void Join(DeleteStatement statement, TableIdentifier table, SchemaMember schema)
        {
            if (table == null || schema == null || schema.Token.Property.IsSimplex)
            {
                return;
            }

            //不可变复合属性不支持任何写操作,即在删除操作中不能包含不可变复合属性
            if (schema.Token.Property.Immutable)
            {
                throw new DataException($"The '{schema.FullPath}' is an immutable complex(navigation) property and does not support the delete operation.");
            }

            var join   = statement.Join(table, schema);
            var target = (TableIdentifier)join.Target;

            statement.Tables.Add(target);

            //生成当前导航属性表的继承链关联集
            var joins = this.Join(statement, target, schema.FullPath);

            if (schema.HasChildren)
            {
                foreach (var child in schema.Children)
                {
                    if (joins != null)
                    {
                        join = joins.FirstOrDefault(j => ((TableIdentifier)j.Target).Entity == child.Token.Property.Entity);

                        if (join != null)
                        {
                            target = (TableIdentifier)join.Target;
                        }
                    }

                    this.Join(statement, target, child);
                }
            }
        }
コード例 #4
0
        private void BuildSchema(DataUpdateContext context, UpdateStatement statement, TableIdentifier table, object data, SchemaMember member)
        {
            //如果不允许更新主键,则忽略对主键修改的构建
            if (member.Token.Property.IsPrimaryKey && !context.Options.HasBehaviors(UpdateBehaviors.PrimaryKey))
            {
                return;
            }

            //确认指定成员是否有必须的写入值
            var provided = context.Validate(member.Token.Property, out var value);

            //如果不是批量更新,并且指定成员不是必须要生成的且也没有必须写入的值,则返回
            if (!context.IsMultiple && !Utility.IsGenerateRequired(ref data, member.Name) && !provided)
            {
                return;
            }

            if (member.Token.Property.IsSimplex)
            {
                //忽略不可变属性
                if (member.Token.Property.Immutable && !provided)
                {
                    return;
                }

                //创建当前单值属性的对应的字段标识
                var field = table.CreateField(member.Token);

                if (typeof(Operand).IsAssignableFrom(member.Token.MemberType))
                {
                    var operand    = (Operand)member.Token.GetValue(data);
                    var expression = this.OperandConverter.Convert(context, statement, operand);
                    statement.Fields.Add(new FieldValue(field, expression));
                }
                else
                {
                    var parameter = provided ?
                                    Expression.Parameter(field, member, value) :
                                    Expression.Parameter(field, member);

                    statement.Parameters.Add(parameter);

                    //如果当前的数据成员类型为递增步长类型则生成递增表达式
                    if (member.Token.MemberType == typeof(Interval))
                    {
                        /*
                         * 注:默认参数类型为对应字段的类型,而该字段类型可能为无符号数,
                         * 因此当参数类型为无符号数并且步长为负数(递减),则可能导致参数类型转换溢出,
                         * 所以必须将该参数类型重置为有符号整数。
                         */
                        parameter.DbType = System.Data.DbType.Int32;

                        //字段设置项的值为「字段+参数」的加法表达式
                        statement.Fields.Add(new FieldValue(field, field.Add(parameter)));
                    }
                    else
                    {
                        //字段设置项的值即为参数
                        statement.Fields.Add(new FieldValue(field, parameter));
                    }
                }
            }
            else
            {
                //不可变复合属性不支持任何写操作,即在修改操作中不能包含不可变复合属性
                if (member.Token.Property.Immutable)
                {
                    throw new DataException($"The '{member.FullPath}' is an immutable complex(navigation) property and does not support the update operation.");
                }

                var complex = (IDataEntityComplexProperty)member.Token.Property;

                if (complex.Multiplicity == DataAssociationMultiplicity.Many)
                {
                    //注:在构建一对多的导航属性的UPSERT语句时不能指定容器数据(即data参数值为空),因为批量操作语句不支持在构建阶段绑定到具体数据
                    var upserts = UpsertStatementBuilder.BuildUpserts(context, complex.Foreign, null, member, member.Children);

                    //将新建的语句加入到主语句的从属集中
                    foreach (var upsert in upserts)
                    {
                        statement.Slaves.Add(upsert);
                    }
                }
                else
                {
                    if (context.Source.Features.Support(Feature.Updation.Multitable))
                    {
                        this.BuildComplex(context, statement, data, member);
                    }
                    else
                    {
                        this.BuildComplexStandalone(context, statement, data, member);
                    }
                }
            }
        }
コード例 #5
0
        /// <summary>
        ///		<para>从指定的表标识对应的实体开始进行路径展开。</para>
        ///		<para>注:展开过程包括对父实体的属性集的搜索。</para>
        /// </summary>
        /// <param name="table">指定的进行展开的起点。</param>
        /// <param name="path">指定要展开的成员路径,支持多级导航属性路径。</param>
        /// <param name="step">指定路径中每个属性的展开回调函数。</param>
        /// <returns>返回找到的结果。</returns>
        public static ReduceResult Reduce(this TableIdentifier table, string path, Func <ReduceContext, ISource> step = null)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (table.Entity == null)
            {
                throw new DataException($"The '{table}' table cannot be expanded.");
            }

            if (string.IsNullOrEmpty(path))
            {
                return(ReduceResult.Failure(table));
            }

            ICollection <IEntityMetadata> ancestors = null;
            IEntityPropertyMetadata       property  = null;
            ISource token      = table;
            var     parts      = path.Split('.');
            var     properties = table.Entity.Properties;

            for (int i = 0; i < parts.Length; i++)
            {
                if (properties == null)
                {
                    return(ReduceResult.Failure(token));
                }

                //如果当前属性集合中不包含指定的属性,则尝试从父实体中查找
                if (!properties.TryGet(parts[i], out property))
                {
                    //尝试从父实体中查找指定的属性
                    property = FindBaseProperty(ref properties, parts[i], ref ancestors);

                    //如果父实体中也不含指定的属性则返回失败
                    if (property == null)
                    {
                        return(ReduceResult.Failure(token));
                    }
                }

                //如果回调函数不为空,则调用匹配回调函数
                //注意:将回调函数返回的结果作为下一次的用户数据保存起来
                if (step != null)
                {
                    token = step(new ReduceContext(string.Join(".", parts, 0, i), token, property, ancestors));
                }

                //清空继承实体链
                if (ancestors != null)
                {
                    ancestors.Clear();
                }

                if (property.IsSimplex)
                {
                    break;
                }
                else
                {
                    properties = GetAssociatedProperties((IEntityComplexPropertyMetadata)property, ref ancestors);
                }
            }

            //返回查找到的结果
            return(new ReduceResult(token, property));
        }
コード例 #6
0
        private void BuildSchema(DataUpdateContext context, UpdateStatement statement, TableIdentifier table, object data, SchemaMember member)
        {
            //忽略主键修改,即不能修改主键
            if (member.Token.Property.IsPrimaryKey)
            {
                return;
            }

            //如果不是批量更新,并且当前成员没有改动则返回
            if (!context.IsMultiple && !this.HasChanges(data, member.Name))
            {
                return;
            }

            if (member.Token.Property.IsSimplex)
            {
                var field     = table.CreateField(member.Token);
                var parameter = Expression.Parameter(ParameterExpression.Anonymous, member, field);

                statement.Fields.Add(new FieldValue(field, parameter));
                statement.Parameters.Add(parameter);
            }
            else
            {
                var complex = (IEntityComplexPropertyMetadata)member.Token.Property;

                if (complex.Multiplicity == AssociationMultiplicity.Many)
                {
                    this.BuildUpsertion(statement, member);
                }
                else
                {
                    table = this.Join(statement, member);

                    if (member.HasChildren)
                    {
                        foreach (var child in member.Children)
                        {
                            BuildSchema(context, statement, table, member.Token.GetValue(data), child);
                        }
                    }
                }
            }
        }
コード例 #7
0
 protected StatementBase(TableIdentifier table)
 {
     this.Table = table ?? throw new ArgumentNullException(nameof(table));
 }
コード例 #8
0
 public SubqueryStatement(IStatementBase host, TableIdentifier table) : base(table)
 {
     this.Host = host ?? throw new ArgumentNullException(nameof(host));
 }
コード例 #9
0
 public ISelectStatementBase Subquery(TableIdentifier table)
 {
     return(new SubqueryStatement(this, table));
 }
コード例 #10
0
        private void BuildSchema(DataUpdateContext context, UpdateStatement statement, TableIdentifier table, object data, SchemaMember member)
        {
            //忽略主键修改,即不能修改主键
            if (member.Token.Property.IsPrimaryKey)
            {
                return;
            }

            //确认指定成员是否有必须的写入值
            var provided = context.Validate(member.Token.Property, out var value);

            //如果不是批量更新,并且指定成员不是必须要生成的且也没有必须写入的值,则返回
            if (!context.IsMultiple && !Utility.IsGenerateRequired(ref data, member.Name) && !provided)
            {
                return;
            }

            if (member.Token.Property.IsSimplex)
            {
                //忽略不可变属性
                if (member.Token.Property.Immutable && !provided)
                {
                    return;
                }

                var field     = table.CreateField(member.Token);
                var parameter = provided ?
                                Expression.Parameter(field, member, value) :
                                Expression.Parameter(field, member);

                //如果当前的数据成员类型为递增步长类型则生成递增表达式
                if (member.Token.MemberType == typeof(Interval))
                {
                    /*
                     * 注:默认参数类型为对应字段的类型,而该字段类型可能为无符号数,
                     * 因此当参数类型为无符号数并且步长为负数(递减),则可能导致参数类型转换溢出,
                     * 所以必须将该参数类型重置为有符号整数。
                     */
                    parameter.DbType = System.Data.DbType.Int32;

                    //字段设置项的值为字段加参数的加法表达式
                    statement.Fields.Add(new FieldValue(field, field.Add(parameter)));
                }
                else
                {
                    statement.Fields.Add(new FieldValue(field, parameter));
                }

                statement.Parameters.Add(parameter);
            }
            else
            {
                //不可变复合属性不支持任何写操作,即在修改操作中不能包含不可变复合属性
                if (member.Token.Property.Immutable)
                {
                    throw new DataException($"The '{member.FullPath}' is an immutable complex(navigation) property and does not support the update operation.");
                }

                var complex = (IDataEntityComplexProperty)member.Token.Property;

                if (complex.Multiplicity == DataAssociationMultiplicity.Many)
                {
                    var upserts = UpsertStatementBuilder.BuildUpserts(context, complex.Foreign, data, member, member.Children);

                    //将新建的语句加入到主语句的从属集中
                    foreach (var upsert in upserts)
                    {
                        statement.Slaves.Add(upsert);
                    }
                }
                else
                {
                    if (context.Source.Features.Support(Feature.Updation.Multitable))
                    {
                        this.BuildComplex(context, statement, data, member);
                    }
                    else
                    {
                        this.BuildComplexStandalone(context, statement, data, member);
                    }
                }
            }
        }
コード例 #11
0
        private IEnumerable <JoinClause> Join(Aliaser aliaser, DeleteStatement statement, TableIdentifier table, string fullPath = null)
        {
            if (table == null || table.Entity == null)
            {
                yield break;
            }

            var super = table.Entity.GetBaseEntity();

            while (super != null)
            {
                var clause = JoinClause.Create(table,
                                               fullPath,
                                               name => statement.From.TryGet(name, out var join) ? (JoinClause)join : null,
                                               entity => new TableIdentifier(entity, aliaser.Generate()));

                if (!statement.From.Contains(clause))
                {
                    statement.From.Add(clause);
                    statement.Tables.Add((TableIdentifier)clause.Target);
                }

                super = super.GetBaseEntity();

                yield return(clause);
            }
        }