3

我一直在寻找相当长的时间来解决这个问题。

这是交易。我正在构建一个调用 Web API 以获取其数据的网站。我的 Web API 使用一个库,使用存储库模式。我的数据库模型(EF 模型优先)是在库中构建的。在那个模型中,我有一个基类 Pass。然后我有两个派生类,CustomerCard:Pass 和 Voucher:Pass。我的 EF Designer 模型

我有一种方法可以获取所有的 CustomerCards。

public IQueryable<CustomerCard> GetAllPasses() {
        IList<CustomerCard> allCards = new List<CustomerCard>();

        var c_cards = context.Passes;
        foreach (var c_card in c_cards) {
            if (c_card is CustomerCard) {
                allCards.Add((CustomerCard)c_card);
            }
        }
        return allCards.AsQueryable<CustomerCard>();
    }

在我的 ApiController 中,我使用此方法获取通行证并将其返回到网站,如下所示:

    [HttpGet]
    [Queryable]
    public IQueryable<CustomerCard> GetAllPasses(string version) {
        return passRepo.GetAllPasses().AsQueryable();
    }

我的 Web API 返回 JSON 格式。这是我保留引用和内容的配置:

        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling =
            Newtonsoft.Json.PreserveReferencesHandling.Objects;
        json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
        config.Formatters.Remove(config.Formatters.XmlFormatter);

我使用 IQueryable 是因为我希望能够在我的网站上对数据进行分页。api 方法在“/api/v1/passes/all”中可用。

这是奇怪的部分。为了测试我的分页,我每页调用 1 pass。对于我的第一个通行证,它工作正常。但是当我转到我的第二页时,他也得到了正确的通行证,但是对 User 的引用消失了。

正如您在我的模型中看到的,CustomerCard 类有一个属性 User。这表明谁拥有客户卡。

所以这个调用从 pass 加载用户:'api/v1/passes/all?$top=1' 但是当我调用这个时,用户实例是NULL:'api/v1/passes/all?$top= 1&$skip=1'。

但是,当我调用 'api/v1/passes/all?$top=2' 时,加载了第二遍的用户。所以这就是我的想法得到吹嘘的地方!我不明白?为什么用户参考不与第二个一起出现?它与 EF 的延迟加载功能有关吗?

编辑当我在 context.passes 上使用扩展方法 Include 时,会引发错误:

指定的包含路径无效。EntityType 'LCS_Model.Pass' 没有声明名为 'User' 的导航属性。

这是因为作为 dbset 传递,包含 CustomerCard 以及 Voucher。有没有办法告诉我的上下文期望或将其转换为 CustomerCard?

有人可以帮帮我吗。如果你不明白我的问题,请走开!

已经谢谢了!

编辑 2

我的 API 控制器上的方法现在是

[HttpGet]
[Queryable]
public IQueryable<CustomerCard> GetAllPasses(string version) {
     return context.Passes.Include("User").OfType<CustomerCard>();
}

这给了我正确的项目。我的数据库中有 2 张客户卡。两者都来自同一个用户。我的 API 仍然加载了用户。我的网站收到响应的那一刻,用户属性变为空。我的猜测是这是因为它仍然从数组的第一个元素引用同一个用户。那可能吗?如果是,我该如何防止这种情况发生?

4

1 回答 1

2

是的,您需要确保在查询时包含所有相关记录。有关一些示例,请参见this。其次...我不明白为什么您要使用 for 循环来完成所有这些工作...如果您想进行任何分页,那么服务器要做的很多绝对不必要和浪费的工作。我在想,除了您可能想要应用的任何其他过滤器之外,您的 GetAllPasses 应该看起来像这样。

public IQueryable<CustomerCard> GetAllPasses() {
    return context.Passes.Include(r => r.User);
}

编辑(2):我需要更好地阅读。我不得不承认,我不熟悉 EF 中的类型继承。我发现了一些可能在这里起作用的东西: 每个层次结构表,每个具体类型的表,另请参见MSDN Queryable.OfType<TResult>。这是一个猜测,但让我们试试:

public IQueryable<CustomerCard> GetAllPasses() {
    return context.Passes.OfType<CustomerCard>().Include(r => r.User);
}
于 2013-04-09T15:13:01.307 回答