未知の構造化データを保存しているアプリケーションがあります。Foo
したがって、データベースにという名前のテーブルがあり、次のようになっていると仮定します。
CREATE TABLE [dbo].[Foo]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY,
[DataId] INT NOT NULL,
[Bar] VARCHAR(50) NOT NULL,
CONSTRAINT [FK_Foo_Data] FOREIGN KEY ([DataId]) REFERENCES [Data]([Id])
)
また、データをログに記録したプロバイダーと、ログに記録された日時を格納するFoo
という名前のテーブルに関連してData
います。このテーブルは次のようになります。
CREATE TABLE [dbo].[Data]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY,
[ProviderId] INT NOT NULL,
[RecordDateTime] DATETIME NOT NULL,
CONSTRAINT [FK_Data_Provider] FOREIGN KEY ([ProviderId]) REFERENCES [Provider]([Id])
)
Foo
さて、プロバイダー(私はそれが提供するデータについての知識がありません)が次のような名前のクラスを持っていると仮定しましょう:
[Serializable]
public class Foo : ISerializable
{
private string bar;
public string Bar
{
get { return bar; }
set { bar = value; }
}
public Foo()
{
Bar = "Hello World!";
}
public Foo(SerializationInfo info, StreamingContext context)
{
this.bar = info.GetString("Bar");
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Bar", bar);
}
}
したがって、プロバイダーからインスタンスが送信されたら、Foo
それを調べて、データベース内のどのテーブルに挿入するかを決定し、コードブロックが次のようになっていると仮定します。
this.connection.Open();
try
{
var parameters = new
{
ProviderId = registeredProvidersIdBySession[providerKey.ToString()],
RecordDateTime = DateTime.Now,
};
var id = connection.Query<int>("INSERT INTO Data (ProviderId, RecordDateTime) VALUES (@ProviderId, @RecordDateTime); SELECT CAST(SCOPE_IDENTITY() as INT)", parameters).Single();
var t = data.GetType();
var fields = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
var tableName = string.Format("[{0}]", t.Name);
var fieldList = string.Join(", ", fields.Select(p => string.Format("[{0}]", p.Name)).ToArray());
var valueList = fields.Select(p => string.Format("@{0}", p.Name)).ToList();
valueList.Insert(0, "@DataId");
var values = new Dictionary<string, object>();
values.Add("@DataId", id);
foreach (var propertyInfo in fields)
{
values.Add(string.Format("@{0}", propertyInfo.Name), propertyInfo.GetValue(data, null));
}
return connection.Execute(string.Format(
"INSERT INTO {0} ({1}) VALUES ({2})",
tableName,
fieldList,
string.Join(", ", valueList.ToArray())), values);
}
finally
{
this.connection.Close();
}
ご覧のとおり、渡されたオブジェクトのtableName
から取得しています。Type
この例では、それはFoo
です。さらに、リフレクションで挿入するフィールドのリストを収集しています。ただし、問題はDapper
、パラメータ値のためにオブジェクトを送信する必要があることです。さて、型のプロパティを提供する必要がない場合は、DataId
与えられたオブジェクトを渡すだけでDataId
済みますが、ログを正しく関連付けることができるように、そのプロパティが必要です。
私は何を求めていますか?
- 動的タイプを作成する必要が
Dapper
ありますか、それとも何か他のことをすることができますか? - 動的型を作成する必要がある場合、?を使用するよりも簡単な方法はあり
TypeBuilder
ますか?私は前にそれをしました、そして再びそれをすることができます、しかし人それは苦痛です。 - 私が使用する
TypeBuilder
必要がある場合は、私よりも効率的な方法を知っているかもしれないので、あなたの例に興味があります。それで、あなたがいくつかの考えを持っているならば、例を含めてください。
免責事項
Dictionary<string, object>
上記のコード例では、代わりに渡そうとしましたが、Dapper
それを受け入れません。すでにソースコードを見ていたので、そうはならないとは思っていましたが、何かを見逃したいと思っていました。
皆さんありがとう!