Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在IEnumerable中创建泛型方法_C#_Entity Framework_Linq_Generics - Fatal编程技术网

C# 在IEnumerable中创建泛型方法

C# 在IEnumerable中创建泛型方法,c#,entity-framework,linq,generics,C#,Entity Framework,Linq,Generics,好的,给我一点背景资料。 我有一个方法看起来像这样: private static IEnumerable<T> Yield<T>(this IEnumerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models; public async Task<List<UserViewModel>> L

好的,给我一点背景资料。 我有一个方法看起来像这样:

private static IEnumerable<T> Yield<T>(this IEnumerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models;
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();
}
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;
}
私有静态IEnumerable产量(此IEnumerable模型,int numberResults)=>numberResults>0?模型。获取(numberResults):模型;
这对我的项目很有效。我的项目不是使用实体框架的。但是现在它有身份框架,因此它现在使用实体框架

我现在需要列出一些用户,但使用上面相同的功能。 我的方法如下所示:

private static IEnumerable<T> Yield<T>(this IEnumerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models;
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();
}
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;
}
公共异步任务ListByQueryAsync(字符串查询,int-yield) { //用小写字母表示我们的查询 var loweredQuery=query.ToLower(); //获取我们的用户并进行搜索 var users=base.users.Where(m=>m.UserName.ToLower().Contains(loweredQuery)| | m.FirstName.ToLower().Contains(loweredQuery)| | m.LastName.ToLower().Contains(loweredQuery));/.Yield(Yield); //以列表形式返回我们的用户 return wait users.Select(m=>UserFactory.Create(m)).toListSync(); } users变量是IQueryable,它(如果我正确的话)实现了IEnumerable,而且,如果它被转换成任何具体的类,它将执行SQL。因此,我希望获得一个用户列表,然后使用我的静态方法生成结果量。 起初,我只是简单地复制了上面的方法,并写了以下内容:

private static IQuerable<T> Yield<T>(this IQuerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models;
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;
}
私有静态可变现收益率(此可变现模型,int numberResults)=>numberResults>0?模型。获取(numberResults):模型;
这很好,但作为干式原则的拥护者,我决定重复同样的方法,因此我认为因为IQuerable实现了IEumerable我将能够编写一个私有方法来处理bot-public方法。所以我写了这个:

private static IQuerable<T> Yield<T>(this IQuerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models;
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;
}
公共静态类LinqExtensions
{
公共静态IEnumerable收益率(此IEnumerable models,int numberResults)=>models.YieldEnumerable(numberResults);
公共静态IQueryable收益率(此IQueryable模型,int numberResults)=>models.YieldEnumerable(numberResults);
/// 
///按多个结果列出数据库实体或将其全部列出
/// 
///要列出的通用实体
///该查询将自动生成
///要产生的结果数
/// 
私有静态IEnumerable YieldEnumerable(此IEnumerable模型,int numberResults)=>numberResults>0?模型。取(numberResults):模型;
}
现在我得到一个错误声明:

无法将类型“System.Collections.Generic.IEnumerable”隐式转换为“System.Linq.IQuerable”

我可以将IQueryable转换为列表或其他内容,但这意味着我的Yield方法将实际执行SQL,我不希望它这样做。
有人知道我如何解决这个问题吗?

我想我可以通过改变一些类似的方法来解决这个问题:

private static IEnumerable<T> Yield<T>(this IEnumerable<T> models, int numberResults) => numberResults > 0 ? models.Take(numberResults) : models;
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();
}
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;
}
公共静态类LinqExtensions
{
公共静态IEnumerable收益率(此IEnumerable models,int numberResults)=>models.AsQueryable().YieldQueryable(numberResults);
公共静态IQueryable收益率(此IQueryable models,int numberResults)=>models.YieldQueryable(numberResults);
/// 
///按多个结果列出数据库实体或将其全部列出
/// 
///要列出的通用实体
///该查询将自动生成
///要产生的结果数
/// 
私有静态IQueryable YieldQueryable(此IQueryable模型,int numberResults)=>numberResults>0?模型。获取(numberResults):模型;
}

它编译后,用户仍然返回为IQuerable,因此它看起来很有效。

它不起作用的原因是您实际上正在从两个不同的类调用两个不同的
Take
方法

您的
Yield(此IEnumerable models,int numberResults)
正在从类调用

您的
Yield(此iquirable models,int numberResults)
正在从类调用

注意返回类型不同,您得到的错误是因为您的第二个函数需要返回一个
IQueryable
,但是
YieldEnumerable
只返回一个
IEnumerable
。虽然您可以将
IQueryable
隐式转换为
IEnumerable
,但您不能走另一条路

你在回答中发布的工作是迫使这两种方法都通过
Queryable.Take
,内部
Queryable.Take
创建一个包装器,最终调用
Enumerable.Take
作为你的
IEnumable
版本


然而,就我个人而言,我将把它作为两个方法,您没有违反DRY,因为您正在调用两个独立的方法
Enumerable.Yield
Queryable.Yeild
。DRY的要点是降低代码复杂度,使用包装器只会引入额外的开销,并通过引入50%的代码(3行而不是2行)来增加代码复杂度。

注意:执行
公共静态IQueryable产量(此IQueryable models,int numberResults)=>models.YieldEnumerable(numberResults).AsQueryable()也不好做。这将导致数据库将所有行返回到客户端,然后在内存中执行
。Take
。此外,任何
。其中
。选择(
或其他
IQueryable
操作,在
产生
之后发生,也不会成为服务器上发生的SQL查询的一部分。