将 GridView 绑定到 IQueryable
这个问题纯粹是学术性的,因为我从来没有梦想过用真实代码来做到这一点。
使用 LINQ to SQL,我想将 IQueryable
绑定到 GridView。我尝试使用以下代码执行此操作,但出现异常:
无法访问已处置的对象。 对象名称:“Dispose 后访问的 DataContext。”。
下面是我使用 LINQ to SQL 获取 IQueryable
的代码:
public static IQueryable<lu_Genre> GetGenres2() {
using (BooksContextDataContext ctx = new BooksContextDataContext()) {
IQueryable<tabGenre> iq = from g in ctx.tabGenre
select g;
return iq;
}
}
下面是将 GridView 绑定到返回的 IQueryable
的代码。
private void GetGenres() {
gvGenre.DataSource = Genre.GetGenres2();
gvGenre.DataBind();
}
那么为什么这不起作用呢?我可以只使用 .ToList
,返回它,绑定到它,然后它就可以工作,但为什么 IQueryable 不能以相同的方式工作?我真正想要实现的是了解 IQueryable 的功能。
编辑: 我也尝试禁用延迟加载,但没有影响。
This question is purely academic, because I'd never dream of doing this in real code.
Using LINQ to SQL, I want to bind an IQueryable<T>
to a GridView. I tried doing this with the following code, but I get the exception:
Cannot access a disposed object.
Object name: 'DataContext accessed after Dispose.'.
Here is my code that gets an IQueryable<tabGenre>
using LINQ to SQL:
public static IQueryable<lu_Genre> GetGenres2() {
using (BooksContextDataContext ctx = new BooksContextDataContext()) {
IQueryable<tabGenre> iq = from g in ctx.tabGenre
select g;
return iq;
}
}
And here is my code that binds the GridView to the returned IQueryable<T>
.
private void GetGenres() {
gvGenre.DataSource = Genre.GetGenres2();
gvGenre.DataBind();
}
So why doesn't this work? I could just a .ToList<tabGenre>()
, return it, bind to it and then it would work, but why doesn't IQueryable work in the same fashion? What I'm really trying to achieve here is an understanding of what IQueryable can do.
EDIT:
I also tried disabling lazy loading, but to no affect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以将 IQueryable 视为执行查询所需的指令。当您调用 .ToList() 时,您正在执行 IQueryable() 以返回实际数据。当您绑定到 IQueryable() 时,每当调用 DataBind() 时,它都会期望有一个数据源来获取实际数据。
当您设置 gvGenre.DataSource() = Genre.GetGenres2() 时,根据 IQueryable 获取实际数据所需的 DataContext 将在调用 DataBind() 之前被销毁。
如果您调用 .ToList() ,它就会起作用,因为您实际上要出去获取数据,然后将其放入内存。
存储 IQueryable 就像只存储查询一样。如果查询需要使用的数据源不存在,则无法执行查询。
You can think of the IQueryable as the instructions required to execute the query. When you call .ToList(), you are executing the IQueryable() to return actual data. When you bind to IQueryable(), it will expect to have a data source to get the actual data whenever DataBind() is called.
When you set gvGenre.DataSource() = Genre.GetGenres2(), the DataContext required to get actual data based on your IQueryable is destroyed before the call to DataBind() occurs.
It works if you call .ToList() because you're physically going out and getting the data, then putting it memory.
Storing the IQueryable is like storing just the query. You can't execute a query if the datasource it expects to work with doesn't exist.
该 using 块的唯一作用是将 ctx 的生命周期限制为块本身。
iq
的使用寿命取决于ctx
的使用寿命。在使用iq
之前,您明确处置了ctx
。解决这个问题的方法是去掉 using 块,或者强制
iq
在块内进行计算(例如iq = iq.ToList()
),并仅返回该评估的结果。如果您不热衷于后者,请放弃使用。ctx
将在没有人需要后的某个时刻被处置。也许并不完美,但这就是垃圾收集器的生活。您确定如果它继续存在就会产生问题吗?不要修复尚未显示出损坏的东西。The sole effect of that using block is to limit the lifespan of
ctx
to the block itself.The useful lifespan of
iq
is dependent on the lifespan ofctx
. You are explicitly disposing ofctx
beforeiq
is ever used.The way to fix the problem would be to get rid of the using block, or to force
iq
to evaluate within the block (e.g.iq = iq.ToList()
), and return only the results of that evaluation. If you're not keen on doing the latter, just ditch the using.ctx
will be disposed of at some point after nobody needs it. Not perfect, maybe, but that's life with a garbage collector. Are you sure it'll be creating a problem if it stays around? Don't fix what's not yet shown to be broken.就这样做
Just do it like this