Created
October 3, 2012 21:54
-
-
Save nakamura-to/3830127 to your computer and use it in GitHub Desktop.
Simple DB access in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,ABC | |
2,XYZ | |
3,GHI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I inserted a new method to return a DataTable.
Thanks.