2010年3月18日木曜日

SQLite-型のないカラム

SQLiteはデータ型を指定せずにカラムを作成することがで、様々な型を適切(?)に格納することができる。
これは、オブジェクトをプロパティで分割して格納する際に非常に都合がよい。

というわけで、検証。
DecimalがDoubleとして格納されるために有効桁数が小さくなってしまってるので困りもの。どうにか回避方法はないものか。

static void Main(string[] args)
{
ConnectionStringSettings setting = ConfigurationManager.ConnectionStrings["SQLiteConnection"];
DbProviderFactory factory = DbProviderFactories.GetFactory(setting.ProviderName);

using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = setting.ConnectionString;
connection.Open();
DbCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "Insert into Data Values (?, ?, ?)";
{
DbParameter p1 = factory.CreateParameter();
p1.DbType = DbType.Int32;
insertCommand.Parameters.Add(p1);
DbParameter p2 = factory.CreateParameter();
p2.DbType = DbType.String;
insertCommand.Parameters.Add(p2);
DbParameter p3 = factory.CreateParameter();
p3.DbType = DbType.Object;
insertCommand.Parameters.Add(p3);
}
PropertyInfo[] props = typeof(Data).GetProperties();
var propDic = props.ToDictionary(x => x.Name);
using (DbTransaction tran = connection.BeginTransaction())
{
foreach (var data in GetPersonList().Take(2))
{
insertCommand.Parameters[0].Value = data.IntVal;
foreach (var prop in props)
{
insertCommand.Parameters[1].Value = prop.Name;
insertCommand.Parameters[2].Value = prop.GetValue(data, null);
insertCommand.ExecuteNonQuery();
}
}
tran.Commit();
}

DbCommand selectCommand = connection.CreateCommand();
selectCommand.CommandText = "Select * From Data";
using (DbDataReader reader = selectCommand.ExecuteReader())
{
while (reader.Read())
{
var prop = propDic[reader.GetString(1)];
Console.Write(prop.Name + ":" + reader.GetFieldType(2) + ":");
if (prop.PropertyType == typeof(int))
{
Console.WriteLine(reader.GetInt32(2));
}
else if (prop.PropertyType == typeof(long))
{
Console.WriteLine(reader.GetInt64(2));
}
else if (prop.PropertyType == typeof(string))
{
Console.WriteLine(reader.GetString(2));
}
else if (prop.PropertyType == typeof(bool))
{
Console.WriteLine(reader.GetBoolean(2));
}
else if (prop.PropertyType == typeof(DateTime))
{
Console.WriteLine(reader.GetDateTime(2));
}
else if (prop.PropertyType == typeof(double))
{
Console.WriteLine(reader.GetDouble(2));
}
else if (prop.PropertyType == typeof(decimal))
{
Console.WriteLine(reader.GetDecimal(2));
}
}
}
}
}

static IEnumerable<Data> GetPersonList()
{
int id = 0;
while (true)
{
yield return new Data
{
IntVal = id,
LongVal = long.MaxValue,
Text = Path.GetRandomFileName(),
Flag = id % 2 == 0,
Date = new DateTime(2010, 1, 1).AddDays(id),
DoubleVal = double.MaxValue,
DecimalVal = decimal.MaxValue,
};
id++;
}
}

private class Data
{
public int IntVal { get; set; }
public long LongVal { get; set; }
public string Text { get; set; }
public bool Flag { get; set; }
public DateTime Date { get; set; }
public double DoubleVal { get; set; }
public decimal DecimalVal { get; set; }
}

0 件のコメント: