退货类型不正确,但我不明白应该是什么

时间:2016-04-13 18:20:24

标签: c# entity-framework linq

我试图重做此方法只返回相应的记录。下面的原始GetAll()返回了许多不必要的列和数据,因为正在使用EF代理。关闭EF代理会破坏应用程序中的内容,因此我尝试有选择地减少返回的数据以提高性能。

原创GetAll()

    public IEnumerable<OWF_ManagerRelationship> GetAll()
    {
    return context.OWF_ManagerRelationship.Where(x => x.IsActive == true).ToList();
    }

我试图创建的新GetAll()如下所示。这个将包含来自注释掉的Include()语句中的OWF_Onsites表的一些字段。这些将是几个日期字段和一个整数字段。这是我试图减少从此方法返回到调用方法的数据量的地方。我想从Owf_ManagerRelationship上下文返回一个DisplayName字段,从OWF_Onsites表中返回另一个3(OnsiteDate,TargetDate,TargetMonth)。

    public IEnumerable<string> GetAll()
    {
        var managers = context.OWF_ManagerRelationship
            .Where(m => m.IsActive.Value == true)
            //.Include(o => o.OWF_Onsites).Where()
            .Select(x => new {x.DisplayName})
            .ToList();

        return managers;         
    }

上面的return managers有红色的波浪线。它表示&#34;无法将表达式System.Collections.Generic.List<DisplayName:string>转换为返回类型System.Collections.Generic.IEnumerable<string>&#34;。

我知道它无法将匿名类型字符串DisplayName转换为返回类型字符串,但我并不理解为什么。我认为它会起作用,因为DisplayName是一个字符串。一旦我在Include()语句中运行代码,我也不明白返回类型应该是什么。一旦完成,它还应该从OWF_Onsites返回两个日期字段和一个整数字段。

有人可以对这应该是什么样子有所了解吗?包含一些代码以及如何使用Include()中OWF_Onsites表中的两个日期字段(targetDate和OnsiteDate)和整数(TargetMonth)字段将非常有用。

希望我的意图很清楚,以防我尝试这样做是偏离基础的。如果我做错了,请告诉我。

2 个答案:

答案 0 :(得分:5)

您正在尝试返回IEnumerable匿名类型而不是IEnumerable<string>。删除选择中的new,它将起作用:

public IEnumerable<string> GetAll()
{
    var managers = context.OWF_ManagerRelationship
        .Where(m => m.IsActive.Value == true)
        .Select(x => x.DisplayName)
        .ToList();

    return managers;         
}

其他一些值得注意的事项: 您也可以省略.ToList()来简化代码,因为.Select已经返回IEnumerable<string>。请注意,您仍需要稍后枚举查询(例如,使用ToList)以获取结果,因为延迟执行。

public IEnumerable<string> GetAll()
{
    var managers = context.OWF_ManagerRelationship
        .Where(m => m.IsActive.Value == true)
        .Select(x => x.DisplayName);

    return managers;         
}

答案 1 :(得分:2)

你应该看看IQueryable预测来做你想做的事情。以下是一些关于入门的精彩博文:

通过使用这些概念,我能够编写如下的通用存储库方法:

public IEnumerable<T> GetAllProjectTo<T>(params Expression<Func<TEntity, bool>>[] filters)
{
    var query = Table.AsQueryable();
    if (filters != null)
    {
        query = filters.Aggregate(query, (current, where) => current.Where(where));
    }

    return query.Project().To<T>().AsEnumerable();
}

这意味着如果我有这个数据定义(EF):

public class FullModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public int QuantityOnHand { get; set; }
    public double UnitCost { get; set; }
    public DateTime Created { get; set; }
    public string CreatedBy { get; set; }
    public DateTime Updated { get; set; }
    public string UpdatedBy { get; set; }
}

我只想从数据中获得这种表示:

public class ShortModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int QuantityOnHand { get; set; }
    public double UnitCost { get; set; }
}

我现在可以这样做:

IEnumerable<ShortModel> results = _repository.GetAllProjectTo<ShortModel>(a => a.Title.Contains("milk"));

上面的秘诀是Project()和To()的定义。 (请仔细阅读我发布的第二篇博客中的示例。)这两种方法协同工作会影响发送到SQL Server的SQL。在上面的代码示例中,即使使用Select,它也会发出 SELECT * FROM 命令,然后在实现过程中应用SELECT。这意味着,所有受影响的行中的所有数据都将首先返回给您!

在您的情况下,它可能看起来像:

public class MyViewModel
{
    // Name of field MUST match name of field in EF/ORM...
    public string DisplayName { get; set; }
}
public IEnumerable<string> GetAllManagers()
{
    var displayList = context.OWF_ManagerRelationship
        .Where(m => m.IsActive.Value == true)
        .Project()
        .To<MyViewModel>()
        .ToList();

    IEnumerable<string> managers = displayList.Select(a => a.DisplayName).ToList();

    return managers;
}