3

我遇到了一个非常令人困惑的问题,希望有人可以帮助我。在我的应用程序中,我有以下数据结构:

public struct EntityDetails
{
    public string EntityName { get; set; }
    public List<AttributeDetails> Attributes { get; set; }
    public bool EntityExists { get; set; }
}

public struct AttributeDetails
{
    public string AttributeName { get; set; }
    public string DisplayName { get; set; }
    public string DataType { get; set; }
    public string Description { get; set; }
    public bool AttributeExists { get; set; }
}

我使用以下内容实例化对象:

public static List<EntityDetails> entityList { get; set; }

所以,我需要做的是能够根据实体名称和属性名称返回过滤后的属性列表。为此,我编写了以下 LINQ:

public static List<AttributeDetails> GetFilteredAttributeList(string pEntityName, string pAttributeFilter)
{



    return (List<AttributeDetails>)entityList.Where(e => e.EntityName == pEntityName)
                                             .Select(e => e.Attributes
                                                           .Where (a => a.AttributeName
                                                           .Contains (pAttributeFilter)));


 }

最初,当我这样做时,我一开始没有演员表,但它带来了编译时错误,所以我添加了演员表以允许它编译。但是,当它使用此方法时,我收到以下消息:

{“无法将类型为 'WhereSelectListIterator 2[MPYA.BU.CRMClientUpdateTool.CRMAccess.CRMAccessLayer+EntityDetails,System.Collections.Generic.IEnumerable1[MPYA.BU.CRMClientUpdateTool.CRMAccess.CRMAccessLayer+AttributeDetails]]' 的对象转换为类型 'System.Collections.Generic.List`1[MPYA.BU.CRMClientUpdateTool.CRMAccess.CRMAccessLayer+AttributeDetails] ]'。"}

现在,从我所做的研究来看,一个是 IEnumerable 类型,另一个是列表,我理解,但我一生都无法弄清楚如何投射它,所以它是可以接受的!我也尝试过 ToList(),通过扩展方法和其他各种东西进行转换。我还确认数据结构包含正确的数据。

任何帮助,将不胜感激。

更新

抱歉,但由于某种原因,我无法在 8 小时内回复答案sigh。我已按照每个人的建议使用 ToList,现在我收到以下错误:

感谢您到目前为止的答案。在我看来 ToList() 是唯一合乎逻辑的方法,但是当我这样做时,我得到以下编译时错误:

error CS0029: Cannot implicitly convert type 'System.Collections.Generic.List<System.Collections.Generic.IEnumerable<MPYA.BU.CRMClientUpdateTool.CRMAccess.CRMAccessLayer.AttributeDetails>>' to 'System.Collections.Generic.List<MPYA.BU.CRMClientUpdateTool.CRMAccess.CRMAccessLayer.AttributeDetails>'

当我将鼠标悬停在它上面时,实际的错误消息是“System.ArgumentNullException”。

4

5 回答 5

3

您可以简单地通过调用来结束您的 LINQ 查询,.ToList()以将结果转换为List<T>.

要记住的一件事是调用.ToList()LINQ 查询“实现”它,这意味着不再延迟执行;结果现在存储在您的List<T>.

另外,我相信你想使用.SelectMany()从句,而不是.Select(). e.Attributes是一个 List<AttributeDetails>。如果您使用Select(),它将创建一个IEnumarable<list<AttributeDetails>>, 每个元素都是您的一个实体的属性。 SelectMany将合并返回的列表并返回一个IEnumerable<AttributeDetails>,这似乎是您想要的。

最终,您要使用以下内容:

return entityList.Where(e => e.EntityName == pEntityName)
                 .SelectMany(e => e.Attributes
                             .Where (a => a.AttributeName
                                     .Contains(pAttributeFilter)))
                 .ToList();
于 2013-04-25T11:45:18.677 回答
1

You need SelectMany to pull out the attributes into a single list. You also need ToList() to convert the result to a List(). The cast will be unnecessary.

Try

return entityList.Where(e => e.EntityName == pEntityName)
                 .SelectMany(e => e.Attributes
                                   .Where (a => a.AttributeName
                                                 .Contains (pAttributeFilter)))
                 .ToList();
于 2013-04-25T12:15:45.777 回答
1

使用此代码:

 return entityList.Where(e => e.EntityName == pEntityName)
                                             .Select(e => e.Attributes
                                                           .Where (a => a.AttributeName
                                                           .Contains (pAttributeFilter))).ToList()

LINQ 返回不是列表的 IEnumerable,因此您不能将此对象强制转换为列表。当您调用ToList()linq 查询将被执行并转换为列表

于 2013-04-25T11:43:48.293 回答
0

鉴于您Attributes实际上是 的实例AttributeDetails,那么您可以.ToList()在查询结束时调用。但是,另一种合适的方法可能是让您更改方法的签名以返回IEnumerable<AttributeDetails>,这取决于调用者期望的功能。

事实上,如果调用者需要,他们仍然可以在闲暇时转换查询结果,您可以可靠地返回一个更可读和可查询的集合。所以...

public static IEnumerable<AttributeDetails> GetFilteredAttributeList(
  string pEntityName, string pAttributeFilter) {
  return entityList
    .Where(e => e.EntityName == pEntityName)
    .Select(e => e.Attributes
      .Where (a => a.AttributeName.Contains (pAttributeFilter)
    )
  );
}
于 2013-04-25T11:45:14.910 回答
0
public static List<AttributeDetails> GetFilteredAttributeList(string pEntityName, string pAttributeFilter)
    {
        var entityList = new List<EntityDetails>(); //added just to makte it compile

        var filtered =
            from entity in entityList
            where entity.EntityName == pEntityName
            from attribute in entity.Attributes
            where attribute.AttributeName.Contains(pAttributeFilter)
            select attribute;
        return filtered.ToList();
    }
于 2013-04-25T11:49:36.210 回答