2017-04-12 1 views
1

Ok、少しの背景情報。 私はこのようになります方法だった:IEnumerableでジェネリックメソッドを作成する

private static IEnumerable<T> Yield<T>(this IEnumerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models; 

を、これは私のプロジェクトのための罰金働いていました。私のプロジェクトはで、ではなく、エンティティフレームワークです。しかし今ではIdentity Frameworkを持っていて、今度はエンティティフレームワークを使用しています。

ユーザーをリストする必要がありますが、上記の同じ機能を使用します。

public async Task<List<UserViewModel>> ListByQueryAsync(string query, int yield) 
{ 

    // Put our query in lowercase 
    var loweredQuery = query.ToLower(); 

    // Get our users and search 
    var users = base.Users.Where(m => m.UserName.ToLower().Contains(loweredQuery) || m.FirstName.ToLower().Contains(loweredQuery) || m.LastName.ToLower().Contains(loweredQuery)); //.Yield(yield); 

    // Return our users as a list 
    return await users.Select(m => UserFactory.Create(m)).ToListAsync(); 
} 

ユーザー変数がIEnumerableをを実装し、またそれがどの具体的なクラスに変換されている場合、それが実行されます(私は正しいだ場合)のIQueryableです: そのための私の方法は、このようになります。だから私はユーザーのリストを取得したいと思いますへの私の静的メソッドを使用して結果の量はです。 最初に私は単純に上記の方法をコピーして、これを書いた:

private static IQuerable<T> Yield<T>(this IQuerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models; 

これは正常に動作しますが、私は、私は同じ方法を繰り返していることを決定したDRY原則の提唱者であること、私はIQuerable実装しているため考え出しIEumerable私はボットのパブリックメソッドを扱うことができるプライベートメソッドを書くことができます。だから私は、この書いた:

public static class LinqExtensions 
{ 
    public static IEnumerable<T> Yield<T>(this IEnumerable<T> models, int numberResults) => models.YieldEnumerable(numberResults); 
    public static IQueryable<T> Yield<T>(this IQueryable<T> models, int numberResults) => models.YieldEnumerable(numberResults); 

    /// <summary> 
    /// Lists database entities by a number of results or lists them all 
    /// </summary> 
    /// <typeparam name="T">The generic entity to list</typeparam> 
    /// <param name="models">The query to yield</param> 
    /// <param name="numberResults">The number of results to yield</param> 
    /// <returns></returns> 
    private static IEnumerable<T> YieldEnumerable<T>(this IEnumerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models; 
} 

をそして今、私はというエラーを取得:

が暗黙のうちに 'System.Linq.IQuerable' にタイプ 'System.Collections.Generic.IEnumerable' を変換できません。

私はリストか何かとしてのIQueryableを唱えられるが、それは私の収量方法は、実際にSQLを実行しますと、私はそれはそれを行うにはしたくないことを意味します。 誰もこの問題を回避する方法を知っていますか?

答えて

0

は、私はちょうどこのようなビットの周りの方法を変更することでこの問題を解決することができると思う:それは働くよう

public static class LinqExtensions 
{ 
    public static IEnumerable<T> Yield<T>(this IEnumerable<T> models, int numberResults) => models.AsQueryable().YieldQueryable(numberResults); 
    public static IQueryable<T> Yield<T>(this IQueryable<T> models, int numberResults) => models.YieldQueryable(numberResults); 

    /// <summary> 
    /// Lists database entities by a number of results or lists them all 
    /// </summary> 
    /// <typeparam name="T">The generic entity to list</typeparam> 
    /// <param name="models">The query to yield</param> 
    /// <param name="numberResults">The number of results to yield</param> 
    /// <returns></returns> 
    private static IQueryable<T> YieldQueryable<T>(this IQueryable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models; 
} 

これは、コンパイルし、ユーザーがまだIQuerableとして返されますが、それが見えます。

2

実際には2つの異なるクラスから2つの異なるTakeメソッドを呼び出すという理由があります。

Yield<T>(this IEnumerable<T> models, int numberResults)は、System.Linq.Enumerableクラスからpublic static IEnumerable<TSource> Take(this IEnumerable<TSource> source, int count)を呼び出しています。

Yield<T>(this IQuerable<T> models, int numberResults)は、System.Linq.Queryableクラスからpublic static IQuerable<TSource> Take(this IQuerable<TSource> source, int count)を呼び出しています。

戻りタイプが異なることに注意してください.2番目の関数がIQueryable<T>を返す必要があったが、YieldEnumerable<T>を返す必要があったため、エラーはIEnumerable<T>を返します。 IQueryable<T>を暗黙的にIEnumerable<T>にキャストすることはできますが、それ以外の方法はできません。あなたの周りの

作業は内部Queryable.TakeがあなたのIEnumeableバージョンのEnumerable.Takeを呼び出して終了ラッパーを作成して、両方の方法はQueryable.Takeを通過迫られてあなたの答えに投稿しました。

個人的には、私はちょうど2つの方法として残しておきます。Enumerable.YieldQueryable.Yeildという2つの別個のメソッドを呼び出すため、DRYに違反していません。 DRYのポイントは、コードの複雑さを減らすことです。ラッパーを使用すると、オーバーヘッドが導入され、50%多くのコード(2行の代わりに3行)を導入することでコードの複雑さが増します。

+1

注:やっ 'のpublic staticのIQueryable 収量(本のIQueryable モデルは、int型はnumberResults)=> models.YieldEnumerable(はnumberResults).AsQueryable()を;'あまりにも行うことが悪いとなってAVEでしょう。これにより、データベースはすべての行をクライアントに返し、メモリ内で '.Take'を実行します。また、 '.Where'、' .Select( 'または他の' IQueryable ')の操作は、サーバー上で発生するSQLクエリの一部でもありません。 –

関連する問題