ソースについて「貢献」へ該当します。
私の理解であると、著作権および特許権の使用料は両方とも無料
ソース コードを商用または非商用の目的で表示、変更、および再頒布できます。
ソース コードを変更したり、他のユーザーに開示することができます。
利用する場合は、著作権、特許権、商標、出所を表示をアプリ内のどこかに入れておく必要があります。
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
次に使い方ですが、
このように使います。ダイナミック型を省くことによって
実行エラーを防ぎます。と英語で書いてありました。
試してはいません。
例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()
)
ちなみに、中身を動的に変えたい場合フォーマット引数にラムダ関数を入れます。
これで、データないときボタンをだすなど、実装出来ると思います。
以上です。情報がすくなく大変だった。