0

先に進む前に、少し背景を公開する必要があります。次のように、nHibernate といくつかの汎用リポジトリを使用して述語を転送し、エンティティを返すプロジェクトがあります。

public abstract class GenericRepository< T >
{
...
    public virtual T Single( Expression< Func< T, bool > > predicates )
    {
        // Get object from nHibernate session object
        var retObj = Session
            .Query< T >()
            .Where( predicates ).SingleOrDefault();

        return retObj;
    }
...
}

たとえば、次の方法でエンティティを取得できます。

var entity = Context.MyGenericEntityRepository.Single( e => e.Id == id );
// or
var entity = Context.MyGenericEntityRepository.Single( e => e.Name == name );

ただし、プロジェクトの性質上、データベースではなくファイル システム (ファイルの束) に保存されるエンティティもいくつかあります。したがって、次のように、ある種の DataAccess クラスを使用してファイル システムからエンティティを取得する派生リポジトリを使用します。

public class NotGenericRepository
{
...
    // for example
    public IList<Entity> All()
    {
        return _entityDataAccess.All();
    }
...
}

前述のように、2 番目のタイプのエンティティはデータベースに保存されませんが、旅を容易にするために、DataSet と DataTable を使用して一種のメモリ内データベース システムを作成しました。そのため、ソリューションが最初に開始されるとき、CustomDatabase というシングルトンが初期化され、メモリ内に DataTable が作成され、DataTalbes 間の関係が追加され、ファイル システムをスキャンしてテーブルに入力する前にそれらが一般的な DataSet に追加されます。

これを使用して、毎回ファイル システム ツリーをスキャンする代わりに、DataTable をクエリできるようになりました。次に、CustomDatabase でいくつかのイベントを設定して、行が追加/削除/更新されるたびに、変更がファイル システムに反映されるようにします。

ということで…背景は以上です、長くなってすみません…

私の質問はかなり単純になりました。リポジトリから転送されたラムダ式を DataAccess クラスに何らかの方法で変換する方法を探しているので、それを分析して、それに応じて DataTables から選択できます...

たとえば、次のようなリポジトリへの呼び出し:

var entity = Context.MyNotGenericEntityRepository.Single( e => e.Id == id );
// or
var entity = Context.MyNotGenericEntityRepository.Single( e => e.Name == name );

DataAccess 内で次のように変換する必要があります。

DataRow entityRow = CustomDatabase.Tables[ "EntityName" ].AsEnumerable().Where( e => e.Field< Guid >( "Id" ) == id);
// or
DataRow entityRow = CustomDatabase.Tables[ "EntityName" ].AsEnumerable().Where( e => e.Field< string >( "Name" ) == name);

または:

var entity = from myRow in CustomDatabase.Tables[ "EntityName" ].AsEnumerable()
             where myRow.Field<Guid>( "Id" ) == id
             select myRow;
// or
var entity = from myRow in CustomDatabase.Tables[ "EntityName" ].AsEnumerable()
             where myRow.Field<string>( "Name" ) == name
             select myRow;

これを行う方法がまったくわかりません。ネット全体を見てきましたが、問題は、この問題に名前を付ける方法がわからないため、これまでのところあまり見つけられていないことです... :(

この問題に取り組むにはいくつかの方法があると予想しているので、どんな助けも大歓迎です:)

ありがとう!!

4

2 に答える 2

0

派生リポジトリ クラスの例で何がスキップされたかを判断するのは困難ですが、Single をオーバーライド (またはオーバーロード) して All().Single(..) を返すのと同じくらい簡単な場合があります。

于 2012-06-24T13:27:09.000 に答える
0

述語式が質問の形式であると仮定すると、式を a の式に変換し、DataRowそれを使用してエンティティに対応するテーブルをフィルター処理できます。

public static DataRow GetSingleRow<T>(Expression<Func<T, bool>> expr)
{
    var bodyExpr = ((LambdaExpression)expr).Body;
    var binExpr = (BinaryExpression)bodyExpr;
    var propExpr = (MemberExpression)binExpr.Left;
    PropertyInfo targetProperty = (PropertyInfo)propExpr.Member;
    Type targetType = targetProperty.DeclaringType;
    var valueExpr = binExpr.Right;
    string entityName = targetType.Name;

    var fieldMethod = typeof(DataRowExtensions).GetMethod("Field", new[] { typeof(DataRow), typeof(string) });
    var methodInfo = fieldMethod.MakeGenericMethod(targetProperty.PropertyType);
    var propNameExpr = Expression.Constant(targetProperty.Name);
    var rowParamExpr = Expression.Parameter(typeof(DataRow), "dr");
    var fieldInvocationExpr = Expression.Call(methodInfo, rowParamExpr, propNameExpr);

    var eqExpr = Expression.Equal(fieldInvocationExpr, valueExpr);
    Func<DataRow, bool> predicate = Expression.Lambda<Func<DataRow, bool>>(eqExpr, rowParamExpr).Compile();

    return CustomDatabase.Tables[entityName].AsEnumerable().Single(predicate);
}
于 2012-06-24T14:04:31.517 に答える