では、単純に DB を変更して、従来の ADO.NET の DB からほとんど独立できるのでしょうか?
もちろんできますが、それを可能にするためには、この声明を暴く必要があります。
魔法の薬のように見えますが、すべての ADO.NET ステートメントはハードコードされています。
これは ADO.NET の副産物ではなく、アーキテクチャの副産物です。SQL ステートメントを間違った場所に作成しています。プロバイダーごとに異なるステートメントを作成できる、具体的なプロバイダー固有のモデルが必要です。これは思ったほど悪くはありません。ほとんどのステートメントは、リフレクションを利用して自動生成できます。これは単なる特殊なケースです。
たとえば、次のようなモデルがあるとします。
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
SELECT
そして、そこからステートメントを生成したいとしましょう。まず、どのプロパティが PK で、どのプロパティがデータ フィールドであるかを示すために、いくつかの属性が必要です。
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
internal sealed class DataFieldAttribute : Attribute
{
public DataFieldAttribute()
{
}
}
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
sealed class PrimaryKeyAttribute : Attribute
{
public PrimaryKeyAttribute()
{
}
}
そして今、そのクラスを装飾する必要があります:
public class Employee
{
[PrimaryKey]
public int ID { get; set; }
[DataField]
public string Name { get; set; }
[DataField]
public DateTime DateOfBirth { get; set; }
}
次に、ステートメントを作成するための簡単なプロセスが必要なだけなSELECT
ので、まず基本データ モデル クラスを作成しましょう。
public abstract class DataModelBase
{
protected string _primaryKeyField;
protected List<string> _props = new List<string>();
public DataModelBase()
{
PropertyInfo pkProp = this.GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(PrimaryKeyAttribute), false).Length > 0).FirstOrDefault();
if (pkProp != null)
{
_primaryKeyField = pkProp.Name;
}
foreach (PropertyInfo prop in this.GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(DataFieldAttribute), false).Length > 0))
{
_props.Add(prop.Name);
}
}
public virtual string TableName { get { return this.GetType().Name; } }
public virtual string InsertStatement
{
get
{
return string.Format("INSERT INTO [{0}] ({1}) VALUES ({2})",
this.TableName,
GetDelimitedSafeFieldList(", "),
GetDelimitedSafeParamList(", "));
}
}
public virtual string UpdateStatement
{
get
{
return string.Format("UPDATE [{0}] SET {1} WHERE [{2}] = @{2}",
this.TableName,
GetDelimitedSafeSetList(", "),
_primaryKeyField);
}
}
public virtual string DeleteStatement
{
get
{
return string.Format("DELETE [{0}] WHERE [{1}] = @{1}",
this.TableName,
_primaryKeyField);
}
}
public virtual string SelectStatement
{
get
{
return string.Format("SELECT [{0}], {1} FROM [{2}]",
_primaryKeyField,
GetDelimitedSafeFieldList(", "),
this.TableName);
}
}
protected string GetDelimitedSafeParamList(string delimiter)
{
return string.Join(delimiter, _props.Select(k => string.Format("@{0}", k)));
}
protected string GetDelimitedSafeFieldList(string delimiter)
{
return string.Join(delimiter, _props.Select(k => string.Format("[{0}]", k)));
}
protected string GetDelimitedSafeSetList(string delimiter)
{
return string.Join(delimiter, _props.Select(k => string.Format("[{0}] = @{0}", k)));
}
}
そして今、そのデータモデルから継承しましょう:
public class Employee : DataModelBase
そしてブーム、今では必要なときにいつでもこれらのステートメントを取得でき、これらのステートメントは現在、どの具体的なプロバイダーでも機能します。
次に、Dapper を使用してデータを取得しますIDbConnection
。これは、必要に応じて、Oracle バージョンを構築するために簡単に拡張できる、プロバイダーに依存しないソリューションですEmployee
。
このフレームワークには、選択された DB ステートメントに変換される内部の独立した言語ステートメントがあり、これは本当に魔法の薬のように見えます。
確かに、魔法の薬のように見えるかもしれませんが、実際には多くの点で呪いです. 大量のトランザクションとボリュームのデータベースをサポートするニーズに合わせて最適化されたステートメントを作成する柔軟性はありません (少なくとも簡単ではありません)。あなたは本当にここでマスターに服従しています。.NET Entity Framework はこれらのステートメントを作成します。.NET Entity Framework を利用して、この LINQ ステートメントによって生成される SQL を変更するにはどうすればよいかについて、StackOverflow に関する質問がいくつあるか数えきれません。