重述了我的问题,旧文本在下面由于我仍然希望得到答案,我想重申我的问题. Image我有一个带有两个列表的GUI,一个列表显示数据库tblOrders的所有条目列表,另一个列表显示每个订单中的项目.我可以使用Linq2sql或EF从数...
重述了我的问题,旧文本在下面
由于我仍然希望得到答案,我想重申我的问题. Image我有一个带有两个列表的GUI,一个列表显示数据库tblOrders的所有条目列表,另一个列表显示每个订单中的项目.
我可以使用Linq2sql或EF从数据库中获取所有订单,如下所示:
using (DataClasses1DataContext DataContext = new DataClasses1DataContext())
ListOfOrders = DataContext.tblOrder.ToList();
我可以在列表或datagridview中显示这些顺序.然后选择我想要访问表tblItems中的实体集合的其中一个作业.我可以这样做:
ListOfOrders.First().tblItems.toList();
除了我不能,因为我需要已经处理的DataContext.这在某种程度上是有道理的,因为我无法保证自从我检索ListOfOrders以来没有添加到该订单的新项目.理想情况下,我想检查是否添加了tblOrder.tblItems集合,并且只在需要时才从服务器重新检索该集合.
背景是,我的模型有点复杂:它由Orders组成,它由Parts组成,包括Tasks.因此,为了评估每个订单的进度,我必须检索属于订单的所有部件,并且对于每个订单,我必须看到已经完成了多少任务.在一个有200个作业的数据库中,每个都有1到10个部分,这只会让我的程序在响应性方面变慢…
谁能帮我?
原始问题
我发现了很多关于DataContext的问题,但我还没有找到解决问题的方法.
如果我执行以下操作:
using (DataClasses1DataContext DataContext = new DataClasses1DataContext())
ListOfOrders = DataContext.tblOrder.ToList();
这给了我tblOrder表中的实体列表.
但现在我想这样做:
DataTable Orders = new DataTable();
Orders.Columns.Add("Order-ID", typeof(int));
Orders.Columns.Add("Order-Name", typeof(string));
Orders.Columns.Add("Order-Items", typeof(string));
dataGridView1.DataSource = Orders;
foreach (tblOrder Order in ListOfOrders)
{
var newRow = Orders.NewRow();
newRow["Order-ID"] = Order.orderID;
newRow["Order-Name"] = Order.orderName;
newRow["Order-Items"] = string.Join(", ", Order.tblItem.Select(item=> item.itemName).ToList());
// System.ObjectDisposedException
(dataGridView1.DataSource as DataTable).Rows.Add(newRow);
}
我不能,因为访问tblItem表中与外键相关的所有实体似乎没有存储.
什么工作:
DataClasses1DataContext DataContext = new DataClasses1DataContext();
ListOfOrders = DataContext.tblOrder.ToList();
DataTable Orders = new DataTable();
Orders.Columns.Add("Order-ID", typeof(int));
Orders.Columns.Add("Order-Name", typeof(string));
Orders.Columns.Add("Order-Items", typeof(string));
dataGridView1.DataSource = Orders;
foreach (tblOrder Order in ListOfOrders)
{
var newRow = Orders.NewRow();
newRow["Order-ID"] = Order.orderID;
newRow["Order-Name"] = Order.orderName;
newRow["Order-Items"] = string.Join(", ", Order.tblItem.Select(item=> item.itemName).ToList());
(dataGridView1.DataSource as DataTable).Rows.Add(newRow);
}
DataContext.Dispose();
但据我所知,这是不可取的.
编辑
我将我的示例扩展为Controller-View-Pattern.
using System.Collections.Generic;
using System.Linq;
namespace TestApplication
{
class Controller
{
private List<tblOrder> _orders;
public IList<tblOrder> Orders
{
get
{
return _orders;
}
}
public Controller()
{
using (var DataContext = new DataClasses1DataContext())
{
_orders = DataContext.tblOrder.ToList();
}
}
}
}
视图现在从控制器检索Orders:
using System.Data;
using System.Linq;
using System.Windows.Forms;
namespace TestApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Controller controller = new Controller();
DataTable Orders = new DataTable();
Orders.Columns.Add("Order-ID", typeof(int));
Orders.Columns.Add("Order-Name", typeof(string));
Orders.Columns.Add("Order-Items", typeof(string));
dataGridView1.DataSource = Orders;
foreach (tblOrder Order in controller.Orders)
{
var newRow = Orders.NewRow();
newRow["Order-ID"] = Order.orderID;
newRow["Order-Name"] = Order.orderName;
newRow["Order-Items"] = string.Join(", ", Order.tblItem.Select(item=> item.itemName).ToList());
(dataGridView1.DataSource as DataTable).Rows.Add(newRow);
}
}
}
}
可悲的是问题仍然存在……
解决方法:
实体框架延迟加载对象数据,这意味着它尽可能晚地加载最少量的数据.接受你的询问:
ListOfOrders = context.tblOrder.ToList();
在这里,您要求tblOrder表中的所有记录.实体框架不会在您的程序中预读,并且理解您将在处理完上下文后查看tblItem表,因此它假定它可以在以后加载tblItem数据.懒惰,它会加载最低要求:tblOrder中的记录列表.
有两种方法可以解决这个问题:
禁用延迟加载
using (var context = new DataClasses1DataContext())
{
data.Configuration.LazyLoadingEnabled = false;
_orders = context.tblOrder.ToList();
}
使用LazyLoadingEnabled = false实体框架将选择tblOrder表的所有内容以及通过外键与其连接的所有表.这可能需要一段时间并使用大量内存,具体取决于相关表的大小和数量.
(编辑:我的错误,disabling LazyLoading does not enable eager loading和there is no default configuration for eager loading.对错误信息道歉.下面的.Include命令看起来是唯一的方法.)
包括其他表格
using (var context = new DataClasses1DataContext())
{
data.Configuration.LazyLoadingEnabled = false;
_orders = context.tblOrder.Include("tblItems").ToList();
}
这告诉实体框架在加载tblOrders表数据时从前面加载tblItems中的所有相关数据. EF仍然不会从其他相关表中加载任何数据,因此在处理上下文后其他数据将不可用.
但是,这并不能解决过时数据的问题 – 也就是说,随着时间的推移,dataGridView1中的记录将不再是最新的.您可以使用触发刷新的按钮或计时器.最简单的刷新方法是重新执行整个过程 – 重新加载_orders,然后选择性地重新填充dataGridView1.
本文标题为:c# – 在Linq to SQL中处理DataContext后无法访问相关数据
基础教程推荐
- C#指针变量与unsafe的实现 2023-07-18
- asp.net实现遍历Request的信息操作示例 2023-02-09
- Unity Shader实现水波纹效果 2023-02-16
- 聊聊C#中的Mixin的具体用法 2023-06-09
- C#中的委托和事件 2023-05-25
- Unity Shader实现玻璃材质效果 2023-02-16
- c#实现哈夫曼树算法 2023-06-15
- 一文搞懂c# await,async执行流 2023-03-03
- 详解c# 泛型类的功能 2023-03-14
- C#使用NPOI实现Excel和DataTable的互转 2023-05-22