【问题标题】:Webforms data binding with EF Code-First Linq query error带有 EF Code-First Linq 查询错误的 Webforms 数据绑定
【发布时间】:2011-10-04 05:11:58
【问题描述】:

在此示例here 中,Scott 展示了对 dbContext 执行 Linq 查询并将结果直接绑定到 GridView 以显示产品列表。他的例子是使用 Code First 的 CTP4 版本。

但是,当我尝试使用最新版本的 EntityFramework 4.1 做同样的事情时,我收到以下错误:

数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)是 不支持。而是用数据填充 DbSet,例如通过 在 DbSet 上调用 Load,然后绑定到本地数据。

我看到 DBQuery 对象在其 IListSource.GetList() 的实现中故意抛出此错误,用于数据绑定。

任何想法为什么他的例子有效?顺便说一句,我知道我可以通过输入projects.ToList() 来完成这项工作。我的主要问题是发布版本中是否发生了某些更改,导致此类事情不再起作用,或者我是否遗漏了可以解决此错误的地方。

仅供参考,我指的是这样的代码:

MyDbContext db = new MyDbContext();

var projects = from p in db.Projects
               where p.AnotherField == 2
               select p;

grdTest.DataSource = projects;
grdTest.DataBind();

【问题讨论】:

  • 我不知道是否有任何变化,但无论如何您都应该致电ToList,因为上下文是一次性的,您希望在不需要它时将其丢弃。很多时候,这发生在页面呈现之前(并且查询执行 => 异常)。 ToList 将确保在上下文存在时执行您的查询。
  • 虽然您所说的是很好的一般建议,但这个具体问题是关于上述错误以及 Scott 的示例如何工作的。我遇到的错误与在数据绑定期间对 DBQuery 对象调用 IListSource.GetList() 时抛出的缺少上下文 b/c 无关。
  • 是的,这不是您问题的答案。这就是我将其作为评论发布的原因。

标签: c# asp.net data-binding exception-handling entity-framework-4.1


【解决方案1】:

这是一个很长的故事,但我会尽量不让它变得无聊。

从 EF 的第一个版本开始,我们支持直接绑定到查询。对于由此产生的陷阱和混乱,我们获得了足够的经验,因此我们决定在为 EF 4.1 创建的新 API 中明确禁用它。 对我而言,主要问题是 WinForms 和 WPF 数据绑定基础架构假定数据源位于内存中且访问成本低廉。这导致数据绑定经常多次请求绑定列表。在 EF 上,绑定到可重用查询必然意味着需要来自数据库的最新结果,因此我们这样做是为了每次要求绑定列表时,我们都会对数据库重新执行查询。每次有人绑定到查询时,这都会导致至少执行两次查询。

对于许多客户来说,绑定到查询的其他一些方面非常令人困惑或违反直觉。我在这篇博文中探讨了过去的工作方式:http://blogs.msdn.com/b/diego/archive/2008/10/09/quick-tips-for-entity-framework-databinding.aspx

您应该使用 DbContext API 做的是直接绑定到本地数据而不是查询。为此,我们公开了 DbSet.Local,它是一个非常适用于 WPF 的 ObservableCollection,以及将集合包装在 BindingList 中以便在 WinForms 中使用的 ToBindingList 方法。

我可以看到异常消息可以更明确地说明本地属性的存在。我会考虑为此提交一个错误。

希望对你有帮助

【讨论】:

  • 谢谢!这对网络场景有什么影响,我假设我们应该简单地调用 .ToList() 还是 .Local ?
  • 仅供参考,关于 Local 属性的完整异常消息是明确的:“不支持直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery、DbRawSqlQuery)的数据。而是用数据填充 DbSet ,例如通过在 DbSet 上调用 Load,然后绑定到本地数据。对于 WPF 绑定到 DbSet.Local。对于 WinForms 绑定到 DbSet.Local.ToBindingList()。"
  • 感谢您的解释。与 WPF 配合得很好。但是使用 winform 的人呢?例外情况表明 WPF 的解决方案甚至可以使用 winforms。在添加和删除新行时,我不得不这样做。看到这个帖子:link
  • 您是否使用了 ToBindnigList() 扩展方法(确保您导入 system.Data.Entity 命名空间才能看到它)。文档中有更多详细信息:msdn.microsoft.com/en-US/data/jj592872.
  • 由于加载所有数据不切实际,是否有建议使用大型数据集在网页上进行分页?
【解决方案2】:

遇到了同样的问题,发现了这个话题。 ToList() 工作:

using (NorthwindContext context = new NorthwindContext())
{
    var products = from p in context.Products
                   where p.Discontinued == false
                   select p;

    gridView.DataSource = products.ToList();
    gridView.DataBind();
}

【讨论】:

  • 正如您在问题中看到的那样,我说“我知道我可以通过放入 products.ToList() 来完成这项工作”。
【解决方案3】:

在查看 Reflector 中的 EF4 Feature CTP4 发布 dll 时,我可以看到它的 DBQuery 对象没有实现 IListSource.GetList() 并像 EF 4.1 dll 那样抛出异常。我猜想他们有理由不再允许直接绑定到查询,即使它实现了 IEnumerable。

这并不能回答他们为什么要进行此更改,但至少我可以看到它可以在旧版本中运行是有原因的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多