2009-09-01 51 views
8

我已经扩展我的实体以实现其类型的特定接口。我试图执行以下查询:将linq结果转换为列表<MyInterface>

var results = from x in context.MyEntityTable 
       where x.AProperty == AValue 
       select x; 

return results.Count() > 0 ? results.Cast<IApplicationEntity>().ToList() : null; 

不过,我不断收到以下错误:

“LINQ到实体只支持铸造实体数据模型基本类型”

基本上什么我想要做的是始终将原始实体类型的结果转换为它实现的接口的通用列表。

这可能吗?

回答

20

你可以做客户端上的演员,通过调用AsEnumerable扩展方法绕过实体框架查询转换层:

return results.Any() 
     ? results.AsEnumerable().Cast<IApplicationEntity>().ToList() 
     : null; 

然而,最好是反向做Count检查的顺序:

var list = results.AsEnumerable().Cast<IApplicationEntity>().ToList(); 
return list.Count == 0 ? null : list; 
+1

+1,但是这将执行两个数据库查询(对于Count和ToList)......它可能会更好地先调用ToList,然后检查项目数 – 2009-09-01 07:50:23

+0

@Thomas:查看第二个查询。 – 2009-09-01 07:51:42

+0

是的,这是更好的;) – 2009-09-01 07:55:10

0
return results.Count() > 0 ? 
results.Select(result => (IApplicationEntity)result) 
.ToList() : null; 
+0

我不认为它会工作,出于同样的原因铸造方法没有。您需要将查询转换为IEnumerable第一个 – 2009-09-01 07:51:58

+0

该消息指出它不知道如何将linq中的Cast()运算符转换为实体。这实际上是由linq提供者(例如,Linq到Sql,linq到对象等)编写的代码。 其他海报建议将调用改为AsEnumerable以强制使用Linq到对象,并因此Cast()运算符成功。我正在做同样的事情,但使用C#而不是通过明确投影到代码中。试试吧,让我知道它是否有效。 – Spence 2009-09-01 11:15:43

3

如果你想投你的结果是复杂类型,你需要强制代码使用LINQ到对象,而不是LINQ到Entiti ES。

在投射之前调用AsEnumerable扩展方法是这里的诀窍。

尝试以下操作:

var results = from x in context.MyEntityTable 
       where x.AProperty == AValue 
       select x; 

return results.AsEnumerable().Cast<IApplicationEntity>().ToList(); 

另外请注意,这不是明智的检查Count()在枚举的,因为这意味着在集合遍历两次。

+0

其实,这是行不通的。在演员阵容之前,你应该做'AsEnumerable' *。否则,EF将尝试将其转换为查询以在提供程序上运行。 – 2009-09-01 07:47:39

+0

@Mehrdad:为了你自己的好,太快了。我在你的评论之前编辑了这篇文章。 ;) – Noldorin 2009-09-01 07:48:33

相关问题