2011-03-04 75 views
5

这个问题纯粹是学术问题,因为我从来没有想过要在真实代码中这样做。绑定GridView到IQueryable <T>

使用LINQ to SQL,我想一个IQueryable<T>绑定到一个GridView。我试着用下面的代码这样做,但我得到的异常:

无法访问已释放的对象。 对象名称:'在Dispose之后访问DataContext'。

这里是我的代码使用LINQ to SQL得到一个IQueryable<tabGenre>

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<T>

private void GetGenres() { 
    gvGenre.DataSource = Genre.GetGenres2(); 
    gvGenre.DataBind(); 
} 

那么,为什么这不工作?我可以只是一个.ToList<tabGenre>(),返回它,绑定到它然后它会工作,但为什么IQueryable不以同样的方式工作?我真正想在这里实现的是对IQueryable可以做什么的理解。

编辑: 我也尝试禁用延迟加载,但没有影响。

回答

16

所需的指令来执行查询你可以认为的IQueryable的。当您调用.ToList()时,您正在执行IQueryable()以返回实际数据。当绑定到IQueryable()时,每当调用DataBind()时,它都会有一个数据源来获取实际的数据。

当您设置gvGenre.DataSource()= Genre.GetGenres2()时,需要获取基于您的IQueryable的实际数据的DataContext在对DataBind()的调用发生之前被销毁。

它的工作原理,如果你调用.ToList(),因为你身体走出去,让数据,然后把它的内存。

存放的IQueryable就像刚才保存的查询。如果它期望使用的数据源不存在,则不能执行查询。

+0

这对我来说非常有意义。我实际上必须在工作中向同事解释这一点,你的解释是教科书,所以我会使用它。谢谢!! – Jagd 2011-03-04 17:41:55

2

,使用块的唯一作用是将含ctx寿命限制在块本身。

iq的使用寿命取决于ctx的使用寿命。在iq曾被使用之前,你明确地处置ctx

解决问题的方法是摆脱使用块,或强制iq在块内(例如iq = iq.ToList())进行评估,并仅返回该评估的结果。如果你不喜欢做后者,那就放弃使用。在没有人需要它的某个时候,将会丢弃ctx。也许不完美,但这是垃圾收集器的生活。你确定它会一直在创造一个问题吗?不要修复尚未显示被破坏的内容。

+0

感谢您的输入。我知道,摆脱Using块确实解决了问题。我试过了,它工作,但我不是让GC为我清理DataContext的忠实粉丝。我甚至在回复之前尝试加载智商,希望能够继续工作,但事实并非如此。那时候,我开始怀疑智商可能会无限期地绑定到DataContext上,但我想与StackOverflow的精明成员进行核对以确保。再次感谢。 – Jagd 2011-03-04 17:36:58

0
public IQueryable MembershipGetAll() 
    { 


      var obj = (from mem in db.GetTable<MEMBERSHIP>() 
          select new 
          { 
           NAME = mem.MEMBERSHIP.NAME, 
           TYPE = mem.MEMBERSHIP.TYPE, 
           TAX_ID = mem.TAX_RATE.TAX_ID, 
           DISCOUNT = mem.DISCOUNT, 
           DISCOUNT_PERCENT = mem.DISCOUNT_PERCENT, 

          } 
         ).AsQueryable(); 
      return obj; 

    } 


private void LoadMembership() 
{ 
    IQueryable mem = null; 
    mem = eb.MembershipGetAll(); 
    grdMembership.DataSource = mem; 
    grdMembershipRates.DataBind(); 
} 

就做这样的