使用包含()的LINQ to SQL进行预加载

时间:2016-01-04 02:31:07

标签: c# linq lazy-loading eager-loading

我花了两天的时间来反对这个问题,我似乎无法破解它(问题是)。在添加数据库关系之前,相同的代码工作正常,之后我读了一个关于延迟加载的 lot

我有两个数据库表,它们之间有1:1的关系。 PromoCode表跟踪代码,并有一个名为id的PK列。 CustomerPromo表格中有一列PromoId,该列与PromoCodeid相关联。这两个表没有其他关系。我在SQL Server Management Studio中生成了所有这些,然后从数据库生成模型。

为了使事情稍微复杂一点,我在WCF数据服务中这样做,但我不相信应该有所作为(它在添加数据库关系之前有效)。启用日志记录后,我总是在日志文件中使用text:

获取Exception
  

在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();

我已经尝试了#34;魔术字符串"版本:

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() 1}}(this answer说要做到最后,但我认为这仅仅是由于嵌套查询)。我已经阅读了有关.Include() will silently fail的情况,毕竟我已经没有了。

我错过了什么?语法问题?逻辑问题?一旦我得到这个"简单"如果工作正常,我还需要嵌套Include s(即如果CustomerPromo表与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日志以找出&#34; DataContext accessed after Dispose.&#34;。如果我通过网页中的AJAX调用进行相同的查询,我会收到状态为error的AJAX错误(这就是全部!)。

2 个答案:

答案 0 :(得分:6)

当我实际上没有要获取的子数据时,我过早地发布了上一个答案。当时我只对获取父数据感兴趣,that answer工作。

现在当我真正需要子数据的时候,我发现它并没有完全发挥作用。我发现this article表示.Include()(他说Including()但我不确定这是否是拼写错误)已被删除,正确的解决方案是使用DataLoadOptions 。此外,我还需要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后,它将很乐意返回父对象,而无需加载子项,或明确设置DeferredLoadingEnabled = false;

答案 1 :(得分:1)

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

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

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

This link在问题评论中发帖(感谢@Virgil)提示答案。但是,我无法找到一种方法来访问LINQ to SQL的LazyLoadingEnabled(我怀疑它是针对EntityFramework的)。 This page表明LINQ to SQL的解决方案是DeferredLoadingEnabled

以下是DeferredLoadingEnabled上的MSDN文档的链接。