У меня проблема, которую я сначала не заметил, потому что моя машина для разработки была быстрой, а мой набор тестов небольшой. Поэтому я создал небольшой демонстрационный проект, потому что проблему легко воспроизвести, если вы знаете, где искать. Вы можете найти его на моем github https://github.com/PhbsSmn/ExpandIssue
Я пробую простую команду odata:
https://localhost:5001/odata/MasterTables?$filter=Id eq 4&$expand=Childs
Здесь ничего особенного, я запрашиваю только записи, которые равны до id 4 и разверните его дочерние элементы
Мой конструктор моделей, в котором я настраиваю навигацию:
public class ExpandIssueModelBuilder
{
public IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
const int defaultPageSize = 100;
var builder = new ODataConventionModelBuilder(serviceProvider)
{
Namespace = "ExpandIssue"
};
var masterTable = builder.EntitySet<MasterTableDetail>("MasterTables");
masterTable.EntityType.Page(null, defaultPageSize);
masterTable.HasManyBinding(m => m.Childs, "ChildTableInfo");
return builder.GetEdmModel();
}
}
Мой контроллер, где я сопоставляю entityframework с моделью odata
[Produces("application/json")]
public class MasterTablesController : ODataController
{
//...
[EnableQuery(EnableCorrelatedSubqueryBuffering = true, EnsureStableOrdering = false)]
public IQueryable<MasterTableDetail> Get()
{
return _context.MasterTable.Select(m => new MasterTableDetail
{
Id = m.Id,
Name = m.Name,
Childs = m.ChildTable.Select(c => new ChildTableInfo
{
Id = c.Id,
Created = c.Created,
Value = c.Value
})
}).OrderBy(m => m.Id);
}
}
Я не думаю, что делаю какие-то странные вещи, кроме того, что не хочу раскрывать свою модель базы данных.
Когда я открываю профилировщик SQL, я вижу следующий запрос, созданный, когда Команда odata выполняется:
DECLARE @__TypedProperty_2 nvarchar(4000) = N'22bfc7f7-1f8a-4a92-b56b-c25cbb0742bd'
DECLARE @__TypedProperty_3 int = 101
DECLARE @__TypedProperty_0 int = 4
SELECT
[t].[Id], [t].[Name],
[c].[Id], [c].[Created], [c].[Value], @__TypedProperty_2,
[c0].[Id], [c0].[Created], [c0].[Value], CAST(1 AS bit)
FROM
(SELECT TOP(@__TypedProperty_3) [m].[Id], [m].[Name]
FROM [MasterTable] AS [m]
WHERE [m].[Id] = @__TypedProperty_0
ORDER BY [m].[Id]) AS [t]
LEFT JOIN [ChildTable] AS [c] ON [t].[Id] = [c].[MasterTableId]
LEFT JOIN [ChildTable] AS [c0] ON [t].[Id] = [c0].[MasterTableId]
ORDER BY
[t].[Id], [c].[Id], [c0].[Id]
Это было не то, что я ожидал, когда это выполняется. Результат в строках 1.048.576, которые в конечном итоге будут уменьшены до 1024. Я забыл что-то настроить, чтобы я вместо этого можно получить такой запрос:
DECLARE @__TypedProperty_2 nvarchar(4000) = N'22bfc7f7-1f8a-4a92-b56b-c25cbb0742bd'
DECLARE @__TypedProperty_3 int = 101
DECLARE @__TypedProperty_0 int = 4
SELECT
[t].[Id], [t].[Name],
[c].[Id], [c].[Created], [c].[Value], @__TypedProperty_2,
CAST(1 AS bit)
FROM
(SELECT TOP(@__TypedProperty_3) [m].[Id], [m].[Name]
FROM [MasterTable] AS [m]
WHERE [m].[Id] = @__TypedProperty_0
ORDER BY [m].[Id]) AS [t]
LEFT JOIN [ChildTable] AS [c] ON [t].[Id] = [c].[MasterTableId]
ORDER BY
[t].[Id], [c].[Id]
Надеюсь, кто-нибудь сможет мне помочь с этим, мне действительно нравится сила, которую дает мне функция расширения, но это болезненный вопрос.