だけで楽しく運動、必ずしもあなたがそれを実装したいと思います方法:生成されたコードを呼び出す
は次のようになります。私は、SqlCommandsを構築して実行するためのすばやく流暢なインターフェイスを作成しました。
サンプル用法のカップル:
int i = Sql.UsingConnection("sample")
.GetTextCommandFor("Select Top 1 ActorID From Actor Where FirstName = @fname")
.AddParameters(new {fname = "Bob"})
.OnException(e => Console.WriteLine(e.Message))
.ExecuteScalar<int>();
var q = Sql.UsingConnection("sample")
.GetTextCommandFor("Select * From Actor Where [email protected] and ActorID > @id")
.AddParameters(new {id = 1000, fname = "Bob"});
using(var reader = q.ExecuteReader())
{
while(reader.Read())
{
// do something
}
}
実際のクラス(複数可)とのインタフェースは以下の通りです:
public class Sql
{
public static ISqlCommandTypeSelector UsingConnection(string connection)
{
return new SqlBuilder(connection);
}
private class SqlBuilder : ISqlCommandTypeSelector, ISqlParameterManager, ISqlExecutor
{
private string _connection;
private string _sqltext;
private CommandType _commandtype;
private Action<Exception> _exceptionBehavior = DefaultExceptionBehavior;
private IList<SqlParameter> _inParams;
public SqlBuilder(string connection)
{
_connection = ConfigurationManager.ConnectionStrings[connection].ConnectionString;
_inParams = new List<SqlParameter>();
}
public ISqlParameterManager GetTextCommandFor(string text)
{
_sqltext = text;
_commandtype = CommandType.Text;
return this;
}
public ISqlParameterManager GetProcCommandFor(string proc)
{
_sqltext = proc;
_commandtype = CommandType.StoredProcedure;
return this;
}
public ISqlExecutor OnException(Action<Exception> action)
{
_exceptionBehavior = action;
return this;
}
public void ExecuteNonQuery()
{
try
{
using (var connection = new SqlConnection(_connection))
using (var cmd = connection.CreateCommand())
{
ConfigureCommand(cmd);
PopulateParameters(cmd);
connection.Open();
cmd.ExecuteNonQuery();
}
}
catch(Exception ex)
{
_exceptionBehavior(ex);
}
}
public T ExecuteScalar<T>()
{
T result = default(T);
try
{
using (var connection = new SqlConnection(_connection))
using (var cmd = connection.CreateCommand())
{
ConfigureCommand(cmd);
PopulateParameters(cmd);
connection.Open();
result = (T) cmd.ExecuteScalar();
return result;
}
}
catch(InvalidCastException ex)
{
// rethrow?
}
catch(Exception ex)
{
_exceptionBehavior(ex);
}
return result;
}
public IDataReader ExecuteReader()
{
try
{
var connection = new SqlConnection(_connection);
var cmd = connection.CreateCommand();
ConfigureCommand(cmd);
PopulateParameters(cmd);
connection.Open();
var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return reader;
}
catch(Exception ex)
{
_exceptionBehavior(ex);
}
return null;
}
public ISqlExecutor AddParameters(object @params)
{
var type = @params.GetType();
var props = type.GetProperties();
foreach (var propertyInfo in props)
{
var param = new SqlParameter("@" + propertyInfo.Name, propertyInfo.GetValue(@params, null));
param.Direction = ParameterDirection.Input;
_inParams.Add(param);
}
return this;
}
public ISqlExecutor WithoutParams()
{
return this;
}
private void ConfigureCommand(SqlCommand cmd)
{
cmd.CommandText = _sqltext;
cmd.CommandType = _commandtype;
}
private void PopulateParameters(SqlCommand cmd)
{
cmd.Parameters.AddRange(_inParams.ToArray());
}
private static void DefaultExceptionBehavior(Exception e)
{
// do something
}
}
}
public interface ISqlCommandTypeSelector
{
ISqlParameterManager GetTextCommandFor(string text);
ISqlParameterManager GetProcCommandFor(string proc);
}
public interface ISqlExecutor
{
ISqlExecutor OnException(Action<Exception> action);
void ExecuteNonQuery();
T ExecuteScalar<T>();
IDataReader ExecuteReader();
}
public interface ISqlParameterManager
{
ISqlExecutor AddParameters(object @params);
ISqlExecutor WithoutParams();
}
本当にあれば、おそらくいくつかのより多くをリファクタリングすることができ、いくつかの繰り返しのコードがあります繰り返しコードが嫌い。これはちょうど楽しい演習ですが、おそらくデータアクセスをどのようにしたいのでしょうか。これは、書き込まれたときのパラメータもサポートしていません。
+1 - このコードを書いただけで、かなり逐語的に投稿されました。 –
これは非常にクリーンなソリューションのようです。ありがとう! 'SqlDataReader'を開くと同様のことができるでしょうか? – chezy525
@ chezy525:私はこれらの方法をいくつか持っていました。基本的には 'ExecuteDataReader'と' ExecuteScalar'です。出力パラメータを使用する場合は、わずかに異なるソリューションも必要になります。上記のエンタープライズライブラリは、多くの柔軟性が必要な場合にはオプションとなります。 – Thorarin