使用 LINQ 预加载到 SQL 和 Include()
Eager-loading using LINQ to SQL with Include()
我花了 2 天的时间来解决这个问题,但我似乎无法破解它(就是这个问题)。在我添加数据库关系之前,相同的代码工作正常,此后我阅读了很多关于延迟加载的文章。
我有两个数据库 table,它们之间有 1:1 关系。 PromoCode
table 跟踪代码,并有一个名为 id
的 PK 列。 CustomerPromo
table 有一列 PromoId
链接到 PromoCode
table id
。这两个table没有其他关系。我在 SQL Server Management Studio 中生成了所有这些,然后从数据库中生成了模型。
为了使事情稍微复杂一些,我在 WCF 数据服务中执行此操作,但我认为这不会有什么不同(它在添加数据库关系之前起作用)。启用日志记录后,我总是在日志文件中收到带有文本的异常:
DataContext accessed after Dispose.
我的函数当前 returns 来自 table 的所有条目:
using (MsSqlDataContext db = new MsSqlDataContext())
{
// This causes issues with lazy-loading
return db.PromoCodes.ToArray();
}
看了很多articles/pages/answers,都说要用.Include()
方法。但这对我不起作用:
return db.PromoCodes.Include(x => x.CustomerPromos).ToArray();
我也试过 "magic string" 版本:
return db.PromoCodes.Include("CustomerPromos").ToArray();
我设法开始工作的唯一代码是:
PromoCode[] toReturn = db.PromoCodes.ToArray();
foreach (var p in toReturn)
p.CustomerPromos.Load();
return toReturn;
我试过向查询添加 .Where()
条件,我试过 .Select()
,我试过将 .Include()
移到 .Where()
之后( this answer says to do it last, but I think that's only due to nested queries). I've read about scenarios where .Include()
will silently fail,毕竟我还差得远。
我错过了什么?语法问题?逻辑问题?一旦我得到这个 "simple" 案例,我还需要嵌套 Include
s(即如果 CustomerPromo
table 与 Customer
有关系)。
编辑
包括所有相关代码。其余部分是 LINQ to SQL 或 WCF 数据服务配置。这就是全部:
[WebGet]
[OperationContract]
public PromoCode[] Test()
{
using (MsSqlDataContext db = new MsSqlDataContext())
{
return db.PromoCodes.Include(x => x.CustomerPromos).ToArray();
}
}
如果我直接通过浏览器调用它(例如 http://<address>:<port>/DataService.svc/Test
),我会收到一条重置连接消息,并且必须查找 WCF 日志以找出“DataContext accessed after Dispose.
”。如果我通过网页中的 AJAX 调用进行相同的查询,我会收到状态为 error
的 AJAX 错误(仅此而已!)。
编辑: 这并没有完全解决问题。在测试时没有任何子数据,我也没有尝试使用它。这只允许我 return 父对象 对象,而不是 return 子对象。有关完整解决方案,请参阅 .
与我读过的所有内容相反,答案不是使用 .Include()
而是更改上下文选项。
using (MsSqlDataContext db = new MsSqlDataContext())
{
db.DeferredLoadingEnabled = false; // THIS makes all the difference
return db.PromoCodes.ToArray();
}
posted in the question comments (thanks @Virgil) hint at the answer. However I couldn't find a way to access LazyLoadingEnabled
for LINQ to SQL (I suspect it's for EntityFramework instead). This page 表示 LINQ to SQL 的解决方案是 DeferredLoadingEnabled
。
这是 DeferredLoadingEnabled 上的 MSDN 文档的 link。
当我实际上没有任何子数据要获取时,我过早地发布了上一个答案。当时我只对获取父数据感兴趣,并且工作。
现在,当我实际上也需要子数据时,我发现它不能完全工作。我找到 this article which indicates that .Include()
(he says Including()
but I'm not sure if that's a typo) has been removed, and the correct solution is to use DataLoadOptions
. In addition, I also needed to enable Unidirectional Serialisation.
最重要的是,我不再需要 DeferredLoadingEnabled
。所以现在最终代码如下所示:
using (MsSqlDataContext db = new MsSqlDataContext())
{
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<PromoCode>(p => p.CustomerPromos);
db.LoadOptions = options;
return db.PromoCodes.ToArray();
}
设置 Unidirectional Serialisation
后,它会愉快地 return 一个父对象,而不必加载子对象,或者显式设置 DeferredLoadingEnabled = false;
.
我花了 2 天的时间来解决这个问题,但我似乎无法破解它(就是这个问题)。在我添加数据库关系之前,相同的代码工作正常,此后我阅读了很多关于延迟加载的文章。
我有两个数据库 table,它们之间有 1:1 关系。 PromoCode
table 跟踪代码,并有一个名为 id
的 PK 列。 CustomerPromo
table 有一列 PromoId
链接到 PromoCode
table id
。这两个table没有其他关系。我在 SQL Server Management Studio 中生成了所有这些,然后从数据库中生成了模型。
为了使事情稍微复杂一些,我在 WCF 数据服务中执行此操作,但我认为这不会有什么不同(它在添加数据库关系之前起作用)。启用日志记录后,我总是在日志文件中收到带有文本的异常:
DataContext accessed after Dispose.
我的函数当前 returns 来自 table 的所有条目:
using (MsSqlDataContext db = new MsSqlDataContext())
{
// This causes issues with lazy-loading
return db.PromoCodes.ToArray();
}
看了很多articles/pages/answers,都说要用.Include()
方法。但这对我不起作用:
return db.PromoCodes.Include(x => x.CustomerPromos).ToArray();
我也试过 "magic string" 版本:
return db.PromoCodes.Include("CustomerPromos").ToArray();
我设法开始工作的唯一代码是:
PromoCode[] toReturn = db.PromoCodes.ToArray();
foreach (var p in toReturn)
p.CustomerPromos.Load();
return toReturn;
我试过向查询添加 .Where()
条件,我试过 .Select()
,我试过将 .Include()
移到 .Where()
之后( this answer says to do it last, but I think that's only due to nested queries). I've read about scenarios where .Include()
will silently fail,毕竟我还差得远。
我错过了什么?语法问题?逻辑问题?一旦我得到这个 "simple" 案例,我还需要嵌套 Include
s(即如果 CustomerPromo
table 与 Customer
有关系)。
编辑
包括所有相关代码。其余部分是 LINQ to SQL 或 WCF 数据服务配置。这就是全部:
[WebGet]
[OperationContract]
public PromoCode[] Test()
{
using (MsSqlDataContext db = new MsSqlDataContext())
{
return db.PromoCodes.Include(x => x.CustomerPromos).ToArray();
}
}
如果我直接通过浏览器调用它(例如 http://<address>:<port>/DataService.svc/Test
),我会收到一条重置连接消息,并且必须查找 WCF 日志以找出“DataContext accessed after Dispose.
”。如果我通过网页中的 AJAX 调用进行相同的查询,我会收到状态为 error
的 AJAX 错误(仅此而已!)。
编辑: 这并没有完全解决问题。在测试时没有任何子数据,我也没有尝试使用它。这只允许我 return 父对象 对象,而不是 return 子对象。有关完整解决方案,请参阅
与我读过的所有内容相反,答案不是使用 .Include()
而是更改上下文选项。
using (MsSqlDataContext db = new MsSqlDataContext())
{
db.DeferredLoadingEnabled = false; // THIS makes all the difference
return db.PromoCodes.ToArray();
}
LazyLoadingEnabled
for LINQ to SQL (I suspect it's for EntityFramework instead). This page 表示 LINQ to SQL 的解决方案是 DeferredLoadingEnabled
。
这是 DeferredLoadingEnabled 上的 MSDN 文档的 link。
当我实际上没有任何子数据要获取时,我过早地发布了上一个答案。当时我只对获取父数据感兴趣,并且
现在,当我实际上也需要子数据时,我发现它不能完全工作。我找到 this article which indicates that .Include()
(he says Including()
but I'm not sure if that's a typo) has been removed, and the correct solution is to use DataLoadOptions
. In addition, I also needed to enable Unidirectional Serialisation.
最重要的是,我不再需要 DeferredLoadingEnabled
。所以现在最终代码如下所示:
using (MsSqlDataContext db = new MsSqlDataContext())
{
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<PromoCode>(p => p.CustomerPromos);
db.LoadOptions = options;
return db.PromoCodes.ToArray();
}
设置 Unidirectional Serialisation
后,它会愉快地 return 一个父对象,而不必加载子对象,或者显式设置 DeferredLoadingEnabled = false;
.