1

これまでのストーリー....

現在MVC(4)を学んでいます。Controller Bloatでいっぱいのアプリを書いたので、Repositories/UnitOfWork/Service Layers などの追加を開始することにしました。

そこで、一般的な CRUD とレコード検索機能をカプセル化する汎用リポジトリを作成することにしました。

「おしゃべりはやめて、何が問題なの?」と言うのが聞こえます

2 つの Lambda パラメーターを受け取るGetメソッドを作成すると思いました。

  1. filter = レコードの選択/選択解除ロジック
  2. singleOrDefault = パラメータに応じて、1 つのレコードまたはデフォルトを提供します。

get メソッドを含む、要約されたGeneric Repositoryコードを次に示します。

 public class GenericRepository<TEntity> :
    IRepository<TEntity> where TEntity : class 
{

    internal AccountsContext context;
    internal DbSet<TEntity> dbSet;


    /// <summary>
    /// Default Constructor.
    /// </summary>
    /// <param name="context"></param>
    public GenericRepository(AccountsContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }


    public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter, 
        Expression<Func<TEntity, bool>> singleOrDefault)
    {
        IQueryable<TEntity> query = dbSet;

        if (filter != null && singleOrDefault == null)
        {
            query = query.Where(filter);
        }

        if (filter != null && singleOrDefault != null)
        {
            query = query.Where(filter)
                         .SingleOrDefault(singleOrDefault);
        }


        return query.ToList();
    }

これをビルドしようとすると、次のコンパイラが表示されます。

エラー 1 型 'TEntity' を 'System.Linq.IQueryable' に暗黙的に変換できません。明示的な変換が存在します (キャストがありませんか?) G:\Accountable\Accountable\DataAccessLayer\GenericRepository.cs 90 30 Accountable

エラーは.SingleOrDefault(singleOrDefault)行にあります。

あなたの便宜のために、私は私が使用している拡張メソッドの署名を提供しました:

    public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
    public static TSource SingleOrDefault<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

私はそれを解決しようとして何年もの間これを見つめてきました。どんな助けでも大歓迎です。

ご参考までに

私の肥大化したコードでは、コントローラーに次のタイプのコードがあり、これをレポジトリ メソッドに置き換えたいと考えています。これは、レプリケートしようとしているものです。

 LedgerCustomer LedgerCustomer = db.LedgerCustomers.Where(l => l.RecordStatus != "X").SingleOrDefault(l => l.id == id);

 CurrencyType currencyType = db.CurrencyTypes.Where(c => c.RecordStatus != "X")
                .SingleOrDefault(c => c.id == LedgerCustomer.CurrencyTypeId);

問題は次のとおりです。

A) 私は正しい LINQ アプローチを使用していますか? 私の肥大化したコードからの上記のクエリは次のとおりです。

RecordStatus が X (論理的に削除された) ではなく、ID が特定の ID と等しい元帳顧客を選択します。

LedgerCustomer PER id のレコードは 1 つだけであるべきであるため (これらは一意であるため、SingleOrDefault と Where を使用して、論理的に削除された LedgerCustomer を選択解除しました。

B) コンパイラ エラーのヘルプが役立ちます。

4

1 に答える 1

2

問題は (ご想像のとおり) 行にあります。

query = query.Where(filter).SingleOrDefault(singleOrDefault);

queryは IQueryable であるため、これを使用Where(filter).SingleOrDefault(singleOrDefault)してもまったく問題ありません。

問題は、 backの結果を に代入SingleOrDefaultqueryしようとしていることにあります。
SingleOrDefaultは IQueryable を返しませんが、代わりに の 1 つのインスタンスだけを返しますTEntity

于 2012-09-23T11:45:12.530 に答える