【发布时间】:2016-01-25 20:44:53
【问题描述】:
我遇到了 EF 和 IQueryable 的奇怪行为。
public IQueryable<foo> getFoo()
{
IQueryable<foo> query;
string someVar = functies.getSomeInt().ToString();
try
{
query = from sTable in db.someTable
from oTable in db.otherTable
where sTable.Id == oTable.Id
&& sTable.Var == someVar
select sTable;
} catch {}
return query;
}
public Test()
{
var queryFoo = getFoo();
foreach(var foo in queryFoo)
{
//This works fine
}
}
上面的例子运行得很好,但是当你将 someVar 的声明放在 try 块中时,EF 似乎无法将 sTable.Var 与 someVar 进行比较。
public IQueryable<foo> getFoo()
{
IQueryable<foo> query;
try
{
string someVar = functies.getSomeInt().ToString();
query = from sTable in db.someTable
from oTable in db.otherTable
where sTable.Id == oTable.Id
&& sTable.Var == someVar
select sTable;
} catch {}
return query;
}
public Test()
{
var queryFoo = getFoo();
foreach(var foo in queryFoo)
{
//This doesn't work
//unable to create constant value of type 'foo'
}
}
这会导致“无法创建类型为 'foo' 的常量值。在此上下文中仅支持原始类型或枚举类型。”
对于 EF 为何如此行事,是否有任何合乎逻辑的解释? 我真的不明白其中的区别,它可能与变量的范围有关。但这似乎仍然很奇怪。
到目前为止,我做了哪些研究(因此,如果我按照以下示例进行操作,则 someVar 在嵌套更深时不是本地的???):
局部变量,比如下面的orderID变量 例如,在客户端上进行评估。
int orderID = 51987;
IQueryable<SalesOrderHeader> salesInfo =
from s in context.SalesOrderHeaders
where s.SalesOrderID == orderID
select s;
还有
方法参数也在客户端进行评估。传入 MethodParameterExample 方法的 orderID 参数。
public static void MethodParameterExample(int orderID)
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
IQueryable<SalesOrderHeader> salesInfo =
from s in context.SalesOrderHeaders
where s.SalesOrderID == orderID
select s;
foreach (SalesOrderHeader sale in salesInfo)
{
Console.WriteLine("OrderID: {0}, Total due: {1}", sale.SalesOrderID, sale.TotalDue);
}
}
}
Literals and Parametesr on the Client
未更改:
public IQueryable<klassen> getKlassenPerGebruiker(Db.Models.gebruiker gbr)
{
// Connectie met de database maken.
var db = new Datastore.Db.Models.dataContext(); //of type DbContext
IQueryable<klassen> query;
try
{
string jaar = functies.getHuidigStartJaar().ToString();
query = from klas in db.klassens
from kpg in db.klassenpergebruikers
from sj in db.schooljaars
where kpg.Klassen_id == klas.Id
&& kpg.Gebruikers_id == gbr.Id
&& sj.Id == klas.Schooljaar_id
&& sj.Start == jaar
&& kpg.School_id == gbr.School_id
orderby klas.Naam
select klas;
}
catch
{
query = null;
}
}
调用函数;
IQueryable qklassen = gs.getKlassenPerGebruiker((user) Session["user"]);
if (qklassen != null)
{
foreach (klassen klas in qklassen)
{
}
}
【问题讨论】:
-
请学会像程序员一样思考。不要说“EF 似乎无法解决 someVar”。说出发生了什么(行为和/或错误消息)。
-
你现在所拥有的不可能运行良好。如果您的查询构造引发异常,
query将保持未初始化状态,C# 编译器将检测到这种可能性并拒绝您的return query;语句。显示一些实际的工作代码以及非工作代码,其中 only 与工作代码之间的变化就是您要询问的内容。 -
@JonathanWood 更新了帖子。我对在 stackoverflow 上发布问题很陌生。
-
我强烈的感觉是这些示例并不能完全代表您的真实代码。这不应该有任何区别。在现实中,您可能有一些方法返回“
Foo”,该方法在IQueryable执行之前或期间进行评估。 -
嘿@GertArnold,这个例子不能更接近我实际所做的。涉及更多的表(加入 4 获胜)。我想指出的是,我没有返回“Foo”对象,而是在 getFoo() 方法之外评估的 IQueryable。我可以创建一个 testproject 并共享它来调用此行为。
标签: c# entity-framework iqueryable