Skip to content

Instantly share code, notes, and snippets.

@nakamura-to
Created October 3, 2012 21:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nakamura-to/3830127 to your computer and use it in GitHub Desktop.
Save nakamura-to/3830127 to your computer and use it in GitHub Desktop.
Simple DB access in C#
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;
namespace DbConsole
{
public class Db
{
private static readonly string ConnectionString =
ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
private readonly SqlTransaction _tx;
private Db(SqlTransaction tx)
{
_tx = tx;
}
public static T Tx<T>(Func<Db, T> func)
{
T result;
using (var con = new SqlConnection(ConnectionString))
{
con.Open();
using (var tx = con.BeginTransaction(IsolationLevel.ReadCommitted))
{
result = func(new Db(tx));
tx.Commit();
}
}
return result;
}
public IEnumerable<T> Query<T>(string sql, object parameters = null) where T : new()
{
return Run<IEnumerable<T>>(sql, parameters, cmd =>
{
Func<SqlDataReader, int, T> makeRow = GetRowMaker<T>();
var rows = new List<T>();
using (var reader = cmd.ExecuteReader())
{
var count = reader.FieldCount;
while (reader.Read())
{
var row = makeRow(reader, count);
rows.Add(row);
}
}
return rows;
});
}
private static Func<SqlDataReader, int, T> GetRowMaker<T>() where T : new()
{
if (typeof(T) == typeof(Object))
{
return MakeDynamicRow<T>;
}
return MakePocoRow<T>;
}
private static T MakeDynamicRow<T>(SqlDataReader reader, int count) where T : new()
{
IDictionary<string, object> row = new ExpandoObject();
SetFields(reader, count, (name, value) => row[name] = value);
return (T)row;
}
private static T MakePocoRow<T>(SqlDataReader reader, int count) where T : new()
{
var row = new T();
var type = typeof (T);
SetFields(reader, count, (name, value) =>
{
var prop = type.GetProperty(name);
if (prop != null)
{
prop.SetValue(row, value);
}
});
return row;
}
private static void SetFields(SqlDataReader reader, int count, Action<string, object> setField)
{
for (var i = 0; i < count; i++)
{
var name = reader.GetName(i);
var value = reader.GetValue(i);
if (value == DBNull.Value)
{
value = null;
}
setField(name, value);
}
}
public int Execute(string sql, object parameters = null)
{
return Run(sql, parameters, cmd => cmd.ExecuteNonQuery());
}
private T Run<T>(string sql, object parameters, Func<SqlCommand, T> func)
{
T result;
using (var cmd = _tx.Connection.CreateCommand())
{
cmd.CommandText = sql;
cmd.Transaction = _tx;
if (parameters != null)
{
foreach (var prop in parameters.GetType().GetProperties())
{
cmd.Parameters.AddWithValue(prop.Name, prop.GetValue(parameters));
}
}
result = func(cmd);
}
return result;
}
}
}
1,ABC
2,XYZ
3,GHI
using System;
namespace DbConsole
{
class Program
{
static void Main(string[] args)
{
var persons = Db.Tx(db => {
db.Execute("delete from Person");
db.Execute("insert into Person (Id, Name) values (1, 'ABC')");
db.Execute("insert into Person (Id, Name) values (2, 'DEF')");
db.Execute("insert into Person (Id, Name) values (3, 'GHI')");
db.Execute("update Person set Name = @Name where Id = @Id", new { Name = "XYZ", Id = 2});
return db.Query("select * from Person");
});
foreach (var p in persons)
{
Console.WriteLine("{0},{1}", p.Id, p.Name);
}
Console.ReadKey();
}
}
}
@ZackStone
Copy link

I inserted a new method to return a DataTable.
Thanks.

public DataTable QueryToDataTable(string sql, object parameters = null)
{
    return Run<DataTable>(sql, parameters, cmd =>
    {
        DataTable dt = new DataTable();
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        da.Fill(dt);
        da.Dispose();
        return dt;
    });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment