这可能是一个非常愚蠢而且显而易见的问题,但我对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语句返回什么类型的对象。我只是一个可以循环的列表。
答案 0 :(得分:11)
正如其他人所说,此特定查询的结果涉及匿名类型。因此,您无法将该方法注释为返回局部变量的确切类型,因为您无法键入该类型的名称,因为它没有名称;这就是“匿名”的意思。
您可以说该方法会返回IEnumerable<object>
或IEnumerable
或object
甚至dynamic
,但可能更好的做法是进行查询首先返回一个名义类型的序列。
更一般地说:正如其他人所说,查询通常在实践中有某种IEnumerable
或IQueryable
类型。但是,重要的是要意识到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表达式中使用匿名类型 - 并且,正如文档所述:
您不能声明字段,属性,事件或返回类型 具有匿名类型的方法。
答案 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