ソースについて「貢献」へ該当します。


私の理解であると、著作権および特許権の使用料は両方とも無料
    ソース コードを商用または非商用の目的で表示、変更、および再頒布できます。
    ソース コードを変更したり、他のユーザーに開示することができます。
    利用する場合は、著作権、特許権、商標、出所を表示をアプリ内のどこかに入れておく必要があります。


BSD MIT系列のライセンスと判断したので、著作を含め公開します。


Microsoft Public License(Ms-PL)

著作元 URL https://dsqlparser.codeplex.com/license





使い方
改良点は、主にC#バージョンにしたことです。+機能追加
休日に作りました。
            using (DB db2 = new DB())
            {
                int[] array2 = { 1, 2 };
                Dictionary dic = new Dictionary();
                DB.Params obj = new DB.Params();
                obj.AddParams(2, SqlDbType.Int);
                dic.Add("minage1", obj);

                //SQL文字列作成
                string sql = No00006;

                //SQL実行
                SqlCommand cmd = db2.CreateDbCommand(sql, "@", dic);

                //SQL実行
                SqlDataReader reader = cmd.ExecuteReader();

                // DataReaderからDataTableを作成
                DataTable dt = new DataTable();

                //セット
                dt.Load(reader);
            }
            
            
            コピーペーストだと動かないので./DB.zipを使ってください





===============================================================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace WebApplication22
{
    public class DB : IDisposable
    {
        /// 
        /// 値、型情報の構造体です
        /// 
        public struct Params
        {
            /// 
            ///  値、型情報をセットしてください
            /// 
            /// 
            /// 
            /// 
            public static Params Add(object value, SqlDbType msColType)
            {
                return new Params(value, msColType);
            }
            /// 
            /// セッター
            /// 
            /// 
            /// 
            public void AddParams(object value, SqlDbType msColType)
            {
                this.MsColType = msColType;
                this.Value = value;
            }
            /// 
            /// プロパティ
            /// 
            public object Value { get; set; }

            /// 
            /// プロパティ
            /// 
            public SqlDbType MsColType { get; set; }

            /// 
            /// セッター
            /// 
            /// 
            /// 
            public Params(object value, SqlDbType msColType)
            {
                this.MsColType = msColType;
                this.Value = value;
            }

        }
        #region "接続先"

        /// 
        /// 接続先
        /// 
        private SqlConnection con;

        /// 
        /// 接続トランザクションを取得
        /// 
        /// 
        public SqlTransaction GetBeginTransaction()
        {
            return con.BeginTransaction();
        }

        #region "コンストラクタ、デストラクタ"
        /// 
        /// コンストラクタ
        /// 
        public DB()
        {
            //接続先
            //接続先
            string constr = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=""c:\users\user\documents\visual studio 2017\Projects\WebApplication22\WebApplication22\App_Data\Database1.mdf"" ;Integrated Security=True";

            con = new SqlConnection(@constr);

            //開始
            Open();
        }
        #endregion

        /// 
        /// デストラクタ
        /// 
        ~DB()
        {
            Close();

        }

        /// 
        /// 開始
        /// 
        public void Open()
        {
            //接続がオープンされていない場合は、オープン処理を実行する
            if ((con == null) || con.State == ConnectionState.Closed)
            {
                con.Open();
            }
        }

        /// 
        /// 終了
        /// 
        public void Close()
        {
            //接続がオープンされている場合は、クローズ処理を実行する
            if ((con != null) && con.State != ConnectionState.Closed)
            {
                con.Close();
            }
        }

        #endregion

        #region "データーベース処理"


        /// 
        /// DBコマンドを返します 
        /// 
        /// DBコネクション
        /// DynamicSQL
        /// パラメータ接頭語
        /// パラメータ値辞書
        /// 
        /// 
        [Obsolete("代わりに 'Seasar2/2waySql CreateDbCommand()' を使用します。")]
        public SqlCommand CreateDbCommand()
        {
            //接続先が指定
            SqlCommand cmd = con.CreateCommand();

            //パラメータ初期化
            cmd.Parameters.Clear();

            //コマンドを返す
            return cmd;
        }



        #endregion

        #region "Seasar2/2waySql "

        /// 
        /// DBコマンドを返します
        /// 
        /// DBコネクション
        /// DynamicSQL
        /// パラメータ接頭語
        /// パラメータ値辞書
        /// 
        /// 
        public SqlCommand CreateDbCommand(
            string twowaysql,
            string prefix,
            Dictionary @params
            )
        {

            //接続先が指定
            SqlCommand cmd = con.CreateCommand();

            //パラメータ初期化
            cmd.Parameters.Clear();

            #region "2waysqlセット"

            ///パラメータセット関数型 変数を作成
            ///T1=引数,T2=引数,T3=結果セット
            Action paramAdder = (string name, SqlDbType v, object value) =>
            {
                if (cmd.Parameters.Contains(name))
                {
                    return;

                }

                ////パラメータタイプをセットします↓
                SqlParameter prm = cmd.CreateParameter();

                prm.ParameterName = name;

                if (value == null)
                {
                    //値
                    prm.Value = DBNull.Value;
                    //型
                    prm.SqlDbType = v;
                }
                else
                {
                    //値
                    prm.Value = value;
                    //型
                    prm.SqlDbType = v;
                }


                cmd.Parameters.Add(prm);

                ////パラメータタイプをセットします↑
            };

            //コマンドテキスト代入
            cmd.CommandText = Read(twowaysql, prefix, @params, paramAdder);

            if (cmd.CommandText.Any() == false)
            {
                cmd.CommandText = twowaysql;
            }

            #endregion

            //コマンドを返す
            return cmd;
        }


        ///Seasar2/2waySql
        /// 
        /// StaticSQLを作成します
        /// 
        /// 
        /// DynamicSQL
        /// ラメータ接頭語
        /// パラメータ値辞書
        /// 
        /// 
        public static string Read(string dsql, string prefix, Dictionary @params, Action paramAdder)
        {
            return ReadBlock(dsql, prefix, @params, paramAdder);
        }

        /// 
        /// ブロック読み込み
        /// 
        /// 
        /// 
        /// 中身がない場合、コマンド(where、order by)自体を消す
        /// 
        private static string ReadBlock(string dsql, string prefix, Dictionary @params, Action paramAdder)
        {
            //ブロック書式
            const string WHERE_BLOCK
                = "/\\*ds begin\\*/.*?(?(where|order\\sby))(?.*?)/\\*ds end begin\\*/[ ]?";

            StringBuilder s = new StringBuilder();
            int pos = 0;

            //dsqlを解析
            Match m = Regex.Match(dsql, WHERE_BLOCK, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            if (m.Success == false)
            {
                return ReadAsIfBlock(dsql, prefix, @params, paramAdder);
            }

            while (m.Success)
            {
                Group g = m.Groups["command"];
                Group block = m.Groups["block"];
                string parts = ReadAsIfBlock(block.Value, prefix, @params, paramAdder);

                //コマンドテキスト
                if (string.IsNullOrEmpty(parts))
                {
                    //ブロックが空の場合、コマンド句なしとする
                    s.AppendFormat("{0} ", dsql.Substring(pos, m.Index - pos));
                }
                else
                {
                    //ブロックが空でない場合、コマンド句を記述する
                    s.AppendFormat("{0}{1}{2} ", dsql.Substring(pos, m.Index - pos), g.Value, parts.ToString());
                }

                //事後処理
                pos = m.Index + m.Length;
                m = m.NextMatch();
            }

            return s.ToString().TrimEnd();
        }

        /// 
        /// IFブロック読み込み
        /// 
        /// 
        /// 
        /// NULLの場合条件式自体を消す
        /// 
        private static string ReadAsIfBlock(string dsql, string prefix, Dictionary @params, Action paramAdder)
        {
            //書式
            const string IF_BLOCK = "/\\*ds if (?.*?)[ ]?\\!\\=[ ]?null\\*/[ ]?\\r\\n(?.*?)\\r\\n/\\*ds end if\\*/[ ]?";

            StringBuilder s = new StringBuilder();

            int pos = 0;

            //dsqlを解析
            Match m = Regex.Match(dsql, IF_BLOCK, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            if (m.Success == false)
            {
                return ReadAsParamCode(dsql, prefix, @params, paramAdder);
            }

            while (m.Success)
            {
                Group g = m.Groups["name"];
                Group block = m.Groups["block"];

                dynamic val = null;
                if (@params.Keys.Contains(g.Value) == false)
                {
                    val = null;

                }
                else
                {
                    val = ((object)@params[g.Value]);
                }

                string parts = string.Empty;
                
                //if (!(val == null || DBNull.Value.Equals(val)))
                if (!((object)val == null || DBNull.Value.Equals((object)val)))
                {
                    parts = ReadAsParamCode(block.Value, prefix, @params, paramAdder);
                }

                //コマンドテキスト
                if (string.IsNullOrEmpty(parts) == false)
                {
                    //演算子(接頭書式)の処理
                    const string PREFIX_OPERATOR_CODE = "^(?\\s*)(?(and|or)\\s*)(?.*)";

                    Match mPrefix = Regex.Match(parts, PREFIX_OPERATOR_CODE, RegexOptions.IgnoreCase);
                    string tmp = dsql.Substring(pos, m.Index - pos);

                    if (s.Length == 0 && string.IsNullOrEmpty(mPrefix.Groups["operator"].Value) == false)
                    {
                        s.AppendFormat("{0}{1}{2}", tmp, mPrefix.Groups["space"].Value, mPrefix.Groups["code"].Value);
                    }
                    else
                    {
                        s.AppendFormat("{0}{1}", tmp, parts.ToString());
                    }
                }

                //事後処理
                pos = m.Index + m.Length;
                m = m.NextMatch();
            }

            //演算子(接尾書式)の処理
            const string SUFFIX_OPERATOR_CODE = "(?.*)(?(and|or))\\s*$";
            Match opSuffix = Regex.Match(s.ToString(), SUFFIX_OPERATOR_CODE, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            if (opSuffix.Success)
            {
                return opSuffix.Groups["code"].Value.TrimEnd();
            }
            else
            {
                return s.ToString().TrimEnd();
            }
        }

        /// 
        /// パラメータコード読み込み
        /// 
        /// 
        /// 
        /// …/*ds 条件名*/ダミー値 …
        /// Age Between /*ds minage*/30 AND /*ds maxage*/40
        /// 
        private static string ReadAsParamCode(string dsql, string prefix, Dictionary @params, Action paramAdder)
        {
            //パラメータ書式
            const string PARAM_CODE = "/\\*ds (?\\$?)(?[^ ]+)\\*/(?[^ ]+)(? ?)";

            //変数用意            
            StringBuilder s = new StringBuilder();
            int pos = 0;

            //dsqlを解析
            Match m = Regex.Match(dsql, PARAM_CODE, RegexOptions.IgnoreCase);
            if (m.Success == false)
            {
                return dsql;
            }
            Action increment = () =>
            {
                pos = m.Index + m.Length;
                m = m.NextMatch();
            };

            while (m.Success)
            {
                Group g = m.Groups["name"];
                Group sp = m.Groups["space"];

                if (@params.ContainsKey(g.Value) == false)
                {
                    increment.Invoke();
                    continue;
                }

                dynamic val2 = @params[g.Value];

                dynamic val = ((Params)val2).Value;

                ////パラメータ型セット
                SqlDbType valtyp = ((Params)val2).MsColType;

                ////型取得 
                //System.Type type = val.GetType();

                //if (type.Name == "Params")
                //{
                //    //値
                //    val = ((Params)val).Value;
                //}

                string parts = string.Empty;
                if (string.IsNullOrEmpty(m.Groups["hard"].Value))
                {
                    //$で始まらない場合、パラメータ
                    parts = CreateParameterCode(g.Value, val, valtyp, prefix, paramAdder);
                }
                else
                {
                    //$で始まる場合、埋め込み
                    parts = CreateHardCode(g.Value, val);
                }

                //コマンドテキスト
                dynamic pre = dsql.Substring(pos, m.Index - pos);

                // 例 IN /*ds age*/(20,21,22)にマッチ
                if (Regex.IsMatch(pre, "\\sin\\s.*$", RegexOptions.IgnoreCase))
                {
                    // IN句による括弧書き追加
                    parts = parts.Decorate("{0}");
                }
                s.AppendFormat("{0}{1}{2}", pre, parts, sp.Value);

                //事後処理
                increment.Invoke();
            }

            //残った文字列はそのまま付け足す
            s.Append(dsql.Substring(pos, dsql.Length - pos));

            return s.ToString().TrimEnd();
        }

        private static string CreateParameterCode(string name, object val, SqlDbType msColType, string prefix, Action paramAdder)
        {
            dynamic vals = val as ICollection;
            StringBuilder parts = new StringBuilder();

            if (vals == null)
            {
                //標準
                paramAdder.Invoke(name, msColType, val);
                parts.AppendFormat("{0}{1}", prefix, name);
            }
            else
            {
                //配列 IN句など pram →param_1 param_2 pram_3へ配列分変換
                var idx = 0;
                foreach (var item_loopVariable in vals)
                {
                    var item = item_loopVariable;
                    string s = string.Format("{0}_{1}", name, idx);
                    paramAdder.Invoke(s, msColType, item);
                    parts.AppendDelimiter(", ").AppendFormat("{0}{1}", prefix, s);
                    idx += 1;
                }
            }

            return parts.ToString();
        }

        private static string CreateHardCode(string name, object val)
        {
            dynamic vals = val as ICollection;
            StringBuilder parts = new StringBuilder();

            if (vals == null)
            {
                //標準
                parts.Append(val.ToString());
            }
            else
            {
                //配列               
                foreach (var item_loopVariable in vals)
                {
                    var item = item_loopVariable;
                    parts.AppendDelimiter(", ").Append(item.ToString());
                }
            }

            dynamic s = parts.ToString();
            if (s.Contains(";"))
            {
                throw new ArgumentException(";を埋め込むことはできません。");
            }
            return s;
        }

        #region IDisposable Support
        private bool disposedValue = false; // 重複する呼び出しを検知するには

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: マネージ状態を破棄します (マネージ オブジェクト)。
                    Close();
                }

                // TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下のファイナライザーをオーバーライドします。
                // TODO: 大きなフィールドを null に設定します。

                disposedValue = true;
            }
        }


        public void Dispose()
        {
            // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。
            Dispose(true);
            // TODO: 上のファイナライザーがオーバーライドされる場合は、次の行のコメントを解除してください。
            // GC.SuppressFinalize(this);
        }
        #endregion

    }


    /// 
    /// MyExtensions
    /// 
    public static class MyExtensions
    {

        /// 
        /// 区切り文字を追加します。文字が存在しない場合は追加しません
        /// 
        /// 
        /// 
        /// 
        /// 
        public static StringBuilder AppendDelimiter(this StringBuilder source, string delimiter)
        {
            if (source.Length != 0)
            {
                source.Append(delimiter);
            }
            return source;
        }
        /// 
        /// デコレートします
        /// 
        /// 
        /// {0}に現在値が入ります。
        /// 
        /// s.Decorate("({0})")
        public static string Decorate(/*ref*/this string source, string format)
        {
            if (source.Length == 0)
            {
                return source;
            }
            return string.Format(format, source);
        }

    }
    #endregion

}
============================================================================================

ちなみに、今MVCを勉強しててWEBGRIDを拡張したサンプルができたので 公開します。
情報がすくなくあせりました。新しい技術をおぼえるのは楽しいですが大変です。いかがコードです。




namespace System.Web.Mvc.Html
{
    public static class EnumerableExtensions
    {
        public static IEnumerable SafeCast(this IEnumerable source)
        {
            if (source == null)
            {
                return null;
            }
            else
            {
                return source.Cast();
            }

        }
    }
    public class WebGrid : WebGrid
    {
        //強い型付けに修正 dynamic→タイプへ変更
        public WebGrid(IEnumerable source = null,
            IEnumerable columnNames = null,
            string defaultSort = null,
            int rowsPerPage = 10,
            bool canPage = true,
            bool canSort = true,
            string ajaxUpdateContainerId = null,
            string ajaxUpdateCallback = null,
            string fieldNamePrefix = null,
            string pageFieldName = null,
            string selectionFieldName = null,
            string sortFieldName = null,
            string sortDirectionFieldName = null
            )
           : base(source.SafeCast(),
                 columnNames,
                 defaultSort,
                 rowsPerPage,
                 canPage,
                 canSort,
                 ajaxUpdateContainerId,
                 ajaxUpdateCallback,
                 fieldNamePrefix,
                 pageFieldName,
                 selectionFieldName,
                 sortFieldName,
                 sortDirectionFieldName
            )
        {
        }



        public WebGridColumn Column(string columnName = null,
            string header = null,
            Func format = null,
            string style = null,
            bool canSort = true)
        {
            Func wrappedFormat = null;
            if (format != null)
            {
                wrappedFormat = o => format((T)o.Value);
            }
            WebGridColumn column = base.Column(
                          columnName, header,
                          wrappedFormat, style, canSort);
            return column;
        }

        public WebGrid Bind(IEnumerable source,
            IEnumerable columnNames = null,
            bool autoSortAndPage = true,
            int rowCount = -1)
        {
            base.Bind(source.SafeCast(),
                columnNames,
                autoSortAndPage,
                rowCount);
            return this;
        }


    }




    public static class WebGridExtensions
    {
        public static WebGrid Grid(this HtmlHelper htmlHelper, 
            IEnumerable source, 
            IEnumerable columnNames = null, 
            string defaultSort = null, 
            int rowsPerPage = 10, 
            bool canPage = true, bool 
            canSort = true, 
            string ajaxUpdateContainerId = null, 
            string ajaxUpdateCallback = null, 
            string fieldNamePrefix = null,
            string pageFieldName = null, 
            string selectionFieldName = null, 
            string sortFieldName = null, 
            string sortDirectionFieldName = null)
        {
            return new WebGrid(source, 
                columnNames, 
                defaultSort, 
                rowsPerPage, 
                canPage, 
                canSort,
                ajaxUpdateContainerId, 
                ajaxUpdateCallback, 
                fieldNamePrefix, 
                pageFieldName,
                selectionFieldName, 
                sortFieldName,
                sortDirectionFieldName);
        }
    }
}




次に使い方ですが、


このように使います。ダイナミック型を省くことによって
実行エラーを防ぎます。と英語で書いてありました。

試してはいません。


例1
   WebGrid grid = new WebGrid().Bind(
        source: this.Model.People,
         columnNames: new[] { "Name", "Age" },
        autoSortAndPage: false,
        rowCount: this.Model.MaxCount);
        
例2

@(Html.Grid(this.Model.People)

            .GetHtml()
)

ちなみに、中身を動的に変えたい場合フォーマット引数にラムダ関数を入れます。

これで、データないときボタンをだすなど、実装出来ると思います。

以上です。情報がすくなく大変だった。