急切地使用带有Include()的LINQ to SQL加载



我花了两天时间来思考这个问题,但我似乎无法解决它(这就是问题)。在我添加数据库关系之前,同样的代码一直运行良好,从那以后,我读了很多关于延迟加载的文章。

我有两个数据库表,它们之间的关系是1:1。PromoCode表跟踪代码,并有一个名为id的PK列。CCD_ 3表具有链接到CCD_ 5表CCD_ 6的列CCD_。这两张表没有其他关系。我在SQLServerManagementStudio中生成了所有这些,然后从数据库中生成了模型。

为了使事情稍微复杂一点,我在WCF数据服务中这样做,但我认为这不会有什么不同(在添加数据库关系之前它就起作用了)。启用日志记录后,我总是在日志文件中得到一个异常,其文本为:

Dispose之后访问的DataContext。

我的函数当前返回表中的所有条目:

using (MsSqlDataContext db = new MsSqlDataContext())
{
    // This causes issues with lazy-loading
    return db.PromoCodes.ToArray();
}

我读过很多文章/页面/答案,他们都说要使用.Include()方法。但这对我不起作用:

return db.PromoCodes.Include(x => x.CustomerPromos).ToArray();

我也尝试过"魔术串"版本:

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()之后(这个答案表示最后执行,但我认为这只是由于嵌套查询)。我读到过.Include()将默默失败的场景,在经历了所有这些之后,我再也不会接近了。

我错过了什么?语法问题?逻辑问题?一旦我使用了这个"简单"的案例,我还需要嵌套Include(即,如果CustomerPromo表与Customer有关系)。

编辑
包括所有相关代码。剩下的要么是LINQ到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调用进行相同的查询,我会得到一个AJAX错误,状态为error(仅此而已!)。

当我实际上没有任何子数据要获取时,我过早地发布了上一个答案。当时我只对获取父数据感兴趣,这个答案很有效。

现在,当我真的也需要子数据时,我发现它并没有完全起作用。我发现这篇文章表明.Include()(他说Including(),但我不确定这是否是拼写错误)已经被删除,正确的解决方案是使用DataLoadOptions。此外,我还需要启用单向串行化。

最重要的是,我不再需要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之后,它将愉快地返回父对象,而不必加载子对象,或者显式地设置DeferredLoadingEnabled = false;

编辑: 这并没有完全解决问题。测试时没有任何子数据,我也没有尝试使用它。这只允许我返回对象,它不返回子对象。有关完整的解决方案,请参阅此答案

与我所读到的相反,答案不是使用.Include(),而是更改上下文选项。

using (MsSqlDataContext db = new MsSqlDataContext())
{
    db.DeferredLoadingEnabled = false; // THIS makes all the difference
    return db.PromoCodes.ToArray();
}

问题评论中的这个链接(感谢@Virgil)暗示了答案。然而,我找不到访问LINQ to SQL的LazyLoadingEnabled的方法(我怀疑它是用于EntityFramework的)。此页面表明LINQ to SQL的解决方案是DeferredLoadingEnabled

这里有一个链接,指向有关DeferredLoadingEnabled的MSDN文档。

最新更新