Ejemplo n.º 1
0
        /// <summary>
        /// 一括Insert用SQLを生成します。
        /// </summary>
        /// <param name="builder">DBMSに応じたQueryBuilderオブジェクト</param>
        /// <param name="records">挿入するレコード(複数件)</param>
        /// <param name="targetColumns">値設定対象カラムを限定する場合は、対象カラムについての匿名型を返すラムダ式。例:「<c>t => new { t.Col1, t.Col2 }</c>」</param>
        /// <param name="escapeMethod">値をSQLリテラル値へと変換するメソッド。DBMSに応じたエスケープ処理を行うよう実装すること</param>
        /// <param name="sqlMaxLength">一括InsertのSQLの最大文字列長。省略可</param>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <returns>「insert into [テーブル]([各カラム]) values ([各設定値]),([各設定値])...」のSQLについて最大文字列長を超過しないよう分割して返す</returns>
        public static IEnumerable <string> BuildBulkInsert <T>(QueryBuilder builder, IEnumerable <T> records, LambdaExpression targetColumns, Func <object, string> escapeMethod, int sqlMaxLength = 100000000)
        {
            var tableInfo = builder.GetTableInfo <T>();
            var columns   = (targetColumns == null
                ? tableInfo.Columns.Where(c => c.Insert)
                : tableInfo.GetColumns(ExpressionHelper.GetMemberNames(targetColumns.Body))).ToArray();
            var names = new StringBuilder();

            foreach (var column in columns)
            {
                if (names.Length > 0)
                {
                    names.Append(", ");
                }
                names.Append(column.Name);
            }

            var data = new StringBuilder();

            foreach (var record in records)
            {
                var values = new StringBuilder();
                foreach (var column in columns)
                {
                    values.Append(values.Length == 0 ? "(" : ", ");
                    values.Append(targetColumns != null || string.IsNullOrWhiteSpace(column.InsertSQL)
                        ? escapeMethod(MemberAccessor.GetValue(record, column.PropertyInfo))
                        : column.InsertSQL);
                }
                values.Append(")");

                if (data.Length + values.Length >= sqlMaxLength)
                {
                    yield return(data.ToString());

                    data.Clear();
                }
                data.AppendLine(data.Length == 0
                    ? "insert into " + tableInfo.Name + "(" + names.ToString() + ") values"
                    : ",");
                data.Append(values.ToString());
            }
            if (data.Length > 0)
            {
                yield return(data.ToString());
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 式木が表している具体的な値を返します。
        /// </summary>
        /// <param name="exp">値を指定している式木</param>
        /// <returns>値</returns>
        public static object EvaluateValue(this Expression exp)
        {
            // Boxingを展開
            var expression = exp.CastTo <Expression>();

            if (expression is ConstantExpression)
            {   // 定数:値を返す
                return((expression as ConstantExpression).Value);
            }
            if (expression is NewExpression)
            {   // インスタンス生成:生成されたインスタンスを返す
                var expr       = (expression as NewExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                return(expr.Constructor.Invoke(parameters));
            }
            if (expression is NewArrayExpression)
            {   // 配列生成:生成された配列を返す
                var expr = (expression as NewArrayExpression);
                return(expr.Expressions.Select(EvaluateValue).ToArray());
            }
            if (expression is MethodCallExpression)
            {   // メソッド呼び出し:呼び出し結果を返す
                var expr       = (expression as MethodCallExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                var obj        = (expr.Object == null) ? null : EvaluateValue(expr.Object);
                return(expr.Method.Invoke(obj, parameters));
            }
            if (expression is InvocationExpression)
            {   // ラムダ等の呼び出し:呼び出し結果を返す
                var invocation = (expression as InvocationExpression);
                var parameters = invocation.Arguments.Select(x => Expression.Parameter(x.Type)).ToArray();
                var arguments  = invocation.Arguments.Select(EvaluateValue).ToArray();
                var lambda     = Expression.Lambda(invocation, parameters);
                return(lambda.Compile().DynamicInvoke(arguments));
            }
            if (expression is BinaryExpression && expression.NodeType == ExpressionType.ArrayIndex)
            {   // 配列等のインデクサ:そのインデックスの値を返す
                var expr  = (expression as BinaryExpression);
                var array = (Array)EvaluateValue(expr.Left);
                var index = expr.Right.Type == typeof(int)
                          ? (int)EvaluateValue(expr.Right)
                          : (long)EvaluateValue(expr.Right);
                return(array.GetValue(index));
            }

            // メンバ(フィールドまたはプロパティ):プロパティ/フィールド値を取り出す
            // ※インスタンスメンバならインスタンス値を再帰把握
            var member = (expression as MemberExpression);

            if (member != null)
            {
                if (member.Member.MemberType == MemberTypes.Property)
                {
                    var info = (PropertyInfo)member.Member;
                    return((member.Expression != null)
                        ? MemberAccessor.GetValue(EvaluateValue(member.Expression), info)
                        : MemberAccessor.GetStaticValue(info));
                }
                if (member.Member.MemberType == MemberTypes.Field)
                {
                    var info = (FieldInfo)member.Member;
                    return((member.Expression != null)
                        ? MemberAccessor.GetValue(EvaluateValue(member.Expression), info)
                        : MemberAccessor.GetStaticValue(info));
                }
            }

            // ここまでの処理で値を特定できなかった:実行して値を取り出す
            return(Expression.Lambda(expression).Compile().DynamicInvoke());
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 式木が表している具体的な値を返します。
        /// </summary>
        /// <param name="expression">値を指定している式木</param>
        /// <returns>値</returns>
        public static object EvaluateValue(this Expression expression)
        {
            if (expression is ConstantExpression)
            {   // 定数:値を返す
                return((expression as ConstantExpression).Value);
            }
            if (expression is NewExpression)
            {   // インスタンス生成:生成されたインスタンスを返す
                var expr       = (expression as NewExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                return(expr.Constructor.Invoke(parameters));
            }
            if (expression is NewArrayExpression)
            {   // 配列生成:生成された配列を返す
                var expr = (expression as NewArrayExpression);
                return(expr.Expressions.Select(EvaluateValue).ToArray());
            }
            if (expression is MethodCallExpression)
            {   // メソッド呼び出し:呼び出し結果を返す
                var expr       = (expression as MethodCallExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                var obj        = (expr.Object == null) ? null : EvaluateValue(expr.Object);
                return(expr.Method.Invoke(obj, parameters));
            }
            if (expression is InvocationExpression)
            {   // ラムダ等の呼び出し:呼び出し結果を返す
                var invocation = (expression as InvocationExpression);
                var parameters = invocation.Arguments.Select(x => Expression.Parameter(x.Type)).ToArray();
                var arguments  = invocation.Arguments.Select(EvaluateValue).ToArray();
                var lambda     = Expression.Lambda(invocation, parameters);
                return(lambda.Compile().DynamicInvoke(arguments));
            }
            if (expression is BinaryExpression && expression.NodeType == ExpressionType.ArrayIndex)
            {   // 配列等のインデクサ:そのインデックスの値を返す
                var expr  = (expression as BinaryExpression);
                var array = (Array)EvaluateValue(expr.Left);
                var index = expr.Right.Type == typeof(int)
                          ? (int)EvaluateValue(expr.Right)
                          : (long)EvaluateValue(expr.Right);
                return(array.GetValue(index));
            }

            // フィールド/プロパティ:1つづつたどっていく
            var memberInfoList = new List <MemberInfo>();
            var temp           = CastTo <Expression>(expression);

            while (!(temp is ConstantExpression))
            {
                var member = CastTo <MemberExpression>(temp);
                if (member == null)
                {     // フィールドでもプロパティでもない
                    if (expression != temp)
                    { // 再帰
                        return(EvaluateValue(temp));
                    }
                    else
                    {   // 再帰できない:ラムダ実行により値取得
                        var lambda = Expression.Lambda(expression);
                        return(lambda.Compile().DynamicInvoke());
                    }
                }
                if (member.Expression == null)
                {   // static
                    if (member.Member.MemberType == MemberTypes.Property)
                    {
                        var info = (PropertyInfo)member.Member;
                        return(MemberAccessor.GetStaticValue(info));
                    }
                    if (member.Member.MemberType == MemberTypes.Field)
                    {
                        var info = (FieldInfo)member.Member;
                        return(MemberAccessor.GetStaticValue(info));
                    }
                    throw new EvaluateException("can't evaluate:" + member.Member.ToString());
                }
                // instance
                memberInfoList.Add(member.Member);
                temp = CastTo <Expression>(member.Expression);
            }
            var value = ((ConstantExpression)temp).Value;

            for (var i = memberInfoList.Count - 1; i >= 0; i--)
            {
                var mi = memberInfoList[i];
                if (mi is PropertyInfo)
                {
                    value = MemberAccessor.GetValue(value, (mi as PropertyInfo));
                }
                else if (mi is FieldInfo)
                {
                    value = MemberAccessor.GetValue(value, (mi as FieldInfo));
                }
            }
            return(value);
        }