linq语句返回什么样的对象?

时间:2012-03-06 16:19:39

标签: c# linq entity-framework

这可能是一个非常愚蠢而且显而易见的问题,但我对Linq很新。在我的数据访问层类中,我有这个方法:

static public ? GetAllUrls()
        {



            using (MonitoredUrlsEntities mu = new MonitoredUrlsEntities())
            {


                var query = from urlTbl in mu.UrlLists
                            join histTbl in mu.Histories on
                            urlTbl.ID equals histTbl.UrlID
                            select new
                            {
                                urlTbl.Url,
                                urlTbl.UrlTitle,
                                urlTbl.UrlType,
                                urlTbl.Frequency,
                                urlTbl.Active,
                                urlTbl.LastChangeDate,
                                urlTbl.LastCheckDate,
                                histTbl.DateRun,
                                histTbl.HashValue
                            };

                  return query.ToList();


            }

问号是存在的,因为我不知道linq语句返回什么类型的对象。我只是一个可以循环的列表。

10 个答案:

答案 0 :(得分:11)

正如其他人所说,此特定查询的结果涉及匿名类型。因此,您无法将该方法注释为返回局部变量的确切类型,因为您无法键入该类型的名称,因为它没有名称;这就是“匿名”的意思。

您可以说该方法会返回IEnumerable<object>IEnumerableobject甚至dynamic,但可能更好的做法是进行查询首先返回一个名义类型的序列。

更一般地说:正如其他人所说,查询通常在实践中有某种IEnumerableIQueryable类型。但是,重要的是要意识到LINQ表达式不一定具有任何特定类型。 LINQ实现为语法转换,而不是语义转换。当你说:

var query = from c in customers select c.Name;

编译器盲目地将其转换为:

var query = customers.Select(c=>c.Name);

query的类型是Select碰巧返回的方法。它可能是int!它几乎肯定不是,因为那将是 dumb ,但如果一些有悖常理的人决定制作一个名为Select的方法返回int,那么查询将是类型int

事实证明,我就是这样一个有悖常理的人;我举一个使用LINQ来操作整数的例子:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/07/query-transformations-are-syntactic.aspx

答案 1 :(得分:6)

您在LINQ表达式中使用匿名类型 - 并且,正如文档所述:

  

您不能声明字段,属性,事件或返回类型   具有匿名类型的方法。

http://msdn.microsoft.com/en-us/library/bb397696.aspx

答案 2 :(得分:4)

它返回匿名类型的列表,你不能从方法返回匿名类型(也许如果你使用动态,你可以但它很乱)。而不是使用匿名类型创建一个包含所有属性的新类,并将其填充到投影中:

var query = from urlTbl in mu.UrlLists
            join histTbl in mu.Histories on
                urlTbl.ID equals histTbl.UrlID
            select new YourNewType
            {
                Url = urlTbl.Url,
                UrlTitle = urlTbl.UrlTitle,
                UrlType = urlTbl.UrlType,
                Frequency = urlTbl.Frequency,
                Active = urlTbl.Active,
                LastChangeDate = urlTbl.LastChangeDate,
                LastCheckDate = urlTbl.LastCheckDate,
                DateRun = histTbl.DateRun,
                HashValue = histTbl.HashValue
            };

现在您的方法可以返回IEnumerable<YourNewType>

答案 3 :(得分:3)

嗯,这是List<T>,其中T是某种匿名类型,你不能在自己的代码中说明(匿名类型给出了不可言喻的名称)。

这样做是故意的;在本地使用之外传播匿名类型通常是错误的。

您应该使用具体类型,而不是使用匿名类型。称之为Foo。然后您的返回类型为List<Foo>

答案 4 :(得分:3)

无法从方法中返回匿名类型(就像其他人所说的那样)。创建一个具体类型和新的类型。您的退货类型为IEnumerable<YourType>,如下所示:

// NOTE: I do not know the actual types of these properties, YMMV
public sealed class UrlHistoryList
{
    public string Url { get; set; }
    public string UrlTitle { get; set; }
    public string UrlType { get; set; }
    public int Frequency { get; set; }
    public bool Active { get; set; }
    public DateTime LastChangeDate { get; set; }
    public DateTime LastCheckDate { get; set; }
    public DateTime DateRun { get; set; }
    public int HashValue { get; set; }
}

static public IEnumerable<UrlHistoryList> GetAllUrls()
        {



            using (MonitoredUrlsEntities mu = new MonitoredUrlsEntities())
            {


                var query = from urlTbl in mu.UrlLists
                            join histTbl in mu.Histories on
                            urlTbl.ID equals histTbl.UrlID
                            select new UrlHistoryList
                            {
                                Url = urlTbl.Url,
                                UrlTitle = urlTbl.UrlTitle,
                                UrlType = urlTbl.UrlType,
                                Frequency = urlTbl.Frequency,
                                Active = urlTbl.Active,
                                LastChangeDate = urlTbl.LastChangeDate,
                                LastCheckDate = urlTbl.LastCheckDate,
                                DateRun = histTbl.DateRun,
                                HashValue = histTbl.HashValue
                            };

                  return query.ToList();


            }

答案 5 :(得分:2)

通常,LINQ语句返回IEnumerable / IQueryable,因此您可以使用.ToList()。在您的情况下,由于.ToList(),您将返回List。

如果你删除了ToList(),如果你要做的就是遍历结果,我会把你的返回作为IEnumerable

答案 6 :(得分:2)

返回IQueryable<T>,其中T是查询select new部分中定义的匿名对象。

最后它以List<T>

的形式返回

方法签名应该是:public static List<dynamic> GetAllUrls() 因为static public ? GetAllUrls()似乎无效。

答案 7 :(得分:1)

尝试IEnumerable

如果删除.ToList(),则为IQueryable

答案 8 :(得分:1)

在此示例中,您将返回基于类型IQueryable<T>的匿名对象,因此可以像这样迭代列表

foreach (var item in query)
{
     //you could access to each attribute of the object like this

    string url = item.Url
    string urlTittle = item.UrlTittle
} 

答案 9 :(得分:1)

正如一些答案所指出的那样,您在使用方法的返回类型时遇到问题,因为它是一种匿名类型。你可以用一些技巧来解决这个问题;它们主要涉及在GetAllUrls的调用站点定义匿名类型,将GetAllUrls定义为泛型方法,并允许编译器的类型推断完成剩下的工作。

在这种情况下,最好确保EF和您的数据库在URL和历史记录之间定义关系,并使用EF从每个URL获取历史记录(反之亦然)。例如:

foreach (var url in mu.UrlLists)
    foreach (var history in url.Histories)
    {
        var obj = new {    
                          url.Url,    
                          url.UrlTitle,    
                          url.UrlType,    
                          url.Frequency,    
                          url.Active,    
                          url.LastChangeDate,    
                          url.LastCheckDate,    
                          history.DateRun,    
                          history.HashValue    
                      };
        // do something with obj
  }

或只是

foreach (var url in mu.UrlLists)
    foreach (var history in url.Histories)
        //do something with url and history