私は次の方法を書きました。
public T GetByID(int id)
{
var dbcontext = DB;
var table = dbcontext.GetTable<T>();
return table.ToList().SingleOrDefault(e => Convert.ToInt16(e.GetType().GetProperties().First().GetValue(e, null)) == id);
}
基本的に、これはGenericクラスのメソッドであり、T
はDataContextのクラスです。
このメソッドは、T(GetTable
)のタイプからテーブルを取得し、入力されたパラメーターの最初のプロパティ(常にID)をチェックします。
これに伴う問題は、プロパティでを実行するために最初に要素のテーブルをリストに変換する必要がGetType
あったことですが、テーブルのすべての要素を列挙してに変換する必要があるため、これはあまり便利ではありませんList
。
ToList
テーブル全体でを回避するために、このメソッドをリファクタリングするにはどうすればよいですか?
[アップデート]
テーブルで直接実行できない理由Where
は、次の例外を受け取ったためです。
メソッド'System.Reflection.PropertyInfo[] GetProperties()'には、SQLへの変換がサポートされていません。
GetProperties
SQLに変換できないためです。
[アップデート]
Tのインターフェイスを使用することを提案する人もいますが、問題は、T
パラメーターが[DataContextName] .designer.csで自動生成されるクラスになるため、インターフェイスを実装できないことです(そして、 LINQのこれらすべての「データベースクラス」のインターフェイス。また、DataContextに新しいテーブルを追加するとファイルが再生成されるため、書き込まれたすべてのデータが失われます。
だから、これを行うためのより良い方法がなければなりません...
[アップデート]
Neil Williamsの提案のようにコードを実装しましたが、まだ問題があります。コードの抜粋は次のとおりです。
インターフェース:
public interface IHasID
{
int ID { get; set; }
}
DataContext [コードの表示]:
namespace MusicRepo_DataContext
{
partial class Artist : IHasID
{
public int ID
{
get { return ArtistID; }
set { throw new System.NotImplementedException(); }
}
}
}
一般的な方法:
public class DBAccess<T> where T : class, IHasID,new()
{
public T GetByID(int id)
{
var dbcontext = DB;
var table = dbcontext.GetTable<T>();
return table.SingleOrDefault(e => e.ID.Equals(id));
}
}
この行で例外がスローされています:return table.SingleOrDefault(e => e.ID.Equals(id));
そして例外は次のとおりです:
System.NotSupportedException: The member 'MusicRepo_DataContext.IHasID.ID' has no supported translation to SQL.
[更新]解決策:
DenisTrollerの投稿された回答とCodeRantブログの投稿へのリンクの助けを借りて、私はついに解決策を見つけることができました:
public static PropertyInfo GetPrimaryKey(this Type entityType)
{
foreach (PropertyInfo property in entityType.GetProperties())
{
ColumnAttribute[] attributes = (ColumnAttribute[])property.GetCustomAttributes(typeof(ColumnAttribute), true);
if (attributes.Length == 1)
{
ColumnAttribute columnAttribute = attributes[0];
if (columnAttribute.IsPrimaryKey)
{
if (property.PropertyType != typeof(int))
{
throw new ApplicationException(string.Format("Primary key, '{0}', of type '{1}' is not int",
property.Name, entityType));
}
return property;
}
}
}
throw new ApplicationException(string.Format("No primary key defined for type {0}", entityType.Name));
}
public T GetByID(int id)
{
var dbcontext = DB;
var itemParameter = Expression.Parameter(typeof (T), "item");
var whereExpression = Expression.Lambda<Func<T, bool>>
(
Expression.Equal(
Expression.Property(
itemParameter,
typeof (T).GetPrimaryKey().Name
),
Expression.Constant(id)
),
new[] {itemParameter}
);
return dbcontext.GetTable<T>().Where(whereExpression).Single();
}