Linq to entities:用于匿名类型创建和选择的新Guid(“”)

时间:2013-04-22 14:15:11

标签: vb.net entity-framework linq-to-entities

按照上一个问题(Only parameterless constructors and initializers are supported in LINQ to Entities),我仍然有一个问题。我只是想了解发生了什么以及为什么某些事情在一个案例而不是另一个案例中起作用。

如果要在Linq to entity查询中强制转换字符串参数(例如查询字符串参数),则必须使用新的Guid(request.querystring(“param”))而不是Guid.parse(request.querystring) ( “参数”))。 Guid.parse将抛出异常,因为Linq无法将其转换为SQL。

我经常在我的代码中使用这种技术,但它确实有用。

dim lstResult = DB.MyTable.Where(function(f) f.key = new Guid(request.querystring("param"))).toList()

但是,当我尝试使用Linq查询创建匿名类型时,它会抛出异常:

dim lstResult = DB.MyTable.Where(function(f) f.key = new Guid(request.querystring("param"))).Select(function(f) new With { .guid = f.guid, .name = f.name }).toList()

抛出的异常是:

  

LINQ to Entities

中仅支持无参数构造函数和初始值设定项

我可以(或应该)做的事情是预先声明Guid参数(这可能是一种好习惯),而不是在查询中使用它。它会起作用:

dim myGuid = Guid.parse(request.querystring("param"))
dim lstResult = DB.MyTable.Where(function(f) f.key = myGuid).Select(function(f) new With { .guid = f.guid, .name = f.name }).toList()

所以,我的问题是:为什么在没有创建匿名类型的情况下它会工作?为什么在尝试创建匿名类型时会引发异常?导致此异常的机制是什么?

2 个答案:

答案 0 :(得分:1)

当您声明将通过LINQ执行到实体提供程序的LINQ查询时,您在LINQ中所做的只是构建将传递给基础IQueryable提供程序的表达式树。然后,提供程序将您的LINQ表达式转换为数据库理解的语言(SQL)。

提供者在可以转换为SQL的表达式方面受到限制。您的示例无法转换,因为提供程序无法将Guid构造函数中的方法调用转换为SQL。我想即使你将一个常量值传递给Guid构造函数,你也会得到相同的异常,所以你必须事先创建你需要的Guid。

这是提供者的限制,以及您不能将LINQ与具有LINQ的实体混合到对象这一事实。

答案 1 :(得分:0)

这是一个很好的问题。我很好奇,看看它是提供者还是编译器在这里做的魔术。首先,我将request.querystring("param")移出LINQ,以确保不会干扰。

如果它没有干扰,那么也许可以查看IL以查看编译器[在第一个实例中是否有效]已经使代码摇晃,以便在作为文字插入LINQ语句之前计算Guid语句的值,当涉及匿名类型时,在第二个实例中不做同样的事情......