(代码详细信息在问题末尾...)
我有一个 3 级数据结构,例如
top.Middles[y].Bottoms[z].Secret
,我想要一个包含最内部秘密为“禁止”的所有外层、中层和底层的列表。在 SQL 中我会将其表达为...
SELECT t.id topId, m.id as middleId, b.id as bottomId
FROM Tops t
join m in t.Middles
join b IN m.Bottoms
where b.Secret = 'Forbidden'
这给了我类似的东西
[
{ "topId": "296f9023-f150-45cd-ad38-a7be2ac83f41", "middleId": "101c24bc-71cb-4b6b-a6cf-6979be61be45", "bottomId": "812ac30c-79d4-4c62-94c2-a8cd3eb19bb6" },
{ "topId": "296f9023-f150-45cd-ad38-a7be2ac83f41", "middleId": "101c24bc-71cb-4b6b-a6cf-6979be61be45", "bottomId": "9b298db2-db68-4a0c-82f4-d5bd270aa72b" },
{ "topId": "296f9023-f150-45cd-ad38-a7be2ac83f41", "middleId": "350f63eb-e41a-493f-9e6d-740818242b7e", "bottomId": "56a51a6c-4e6b-4c52-bbc7-0d71b2486c76" },
{ "topId": "1ebdb15f-5864-4e1e-860d-e3a97696da38", "middleId": "ce3bb505-5412-4368-a30e-7f6ce7838a95", "bottomId": "093c7d30-97bb-4fcf-9bd7-0814cbb92571" },
{ "topId": "1ebdb15f-5864-4e1e-860d-e3a97696da38", "middleId": "1b239750-1a91-4f0c-9fb1-b1d9e333349e", "bottomId": "b7c27305-59a3-4af9-93ed-5ca272472d37" },
{ "topId": "1ebdb15f-5864-4e1e-860d-e3a97696da38", "middleId": "a70b3933-3cde-44d0-80a8-fef6d958ce4a", "bottomId": "30c74577-ef59-41ec-8fd2-0ded3f3c30a2" }
]
这符合我的目的...
但我更愿意使用 LINQ 来完成此操作,这样我就可以对属性名称获得强大的类型和编译器意识。
代码存在各种编译器错误,我无法弄清楚这一点。方法名称是
Example.GetTopsContainingTheSecretWord
。
var topsContainingTheSecretWord = new Example().GetTopsContainingTheSecretWord("Forbidden");
public class Outer
{
public string id { get; set; }
public string Name { get; set; }
public List<Middle> Middles { get; set; }
}
public class Middle
{
public string id { get; set; }
public string Name { get; set; }
public List<Inner> Inners { get; set; }
}
public class Inner
{
public string id { get; set; }
public string Secret { get; set; }
public string Name { get; set; }
}
public record ResultRecord(
Guid TopId,
Guid MiddleId,
Guid BottomId
);
public class Example {
public async Task<List<ResultRecord>> GetTopsContainingTheSecretWord(
string secretWord,
CancellationToken cancellationToken = default
)
{
var query = _plansContainer.GetItemLinqQueryable<ResultRecord>(true)
.SelectMany(t => t.Middles)
.SelectMany(m => m.Bottoms.Where(b => b.Secret == secretWord))
.ToFeedIterator();
var results = new List<ResultRecord>();
while (query.HasMoreResults)
{
var response = await query.ReadNextAsync();
results.AddRange(response);
}
return results;
}
}
您将无法使用 linq 生成精确的查询,但可以获得相同的结果。例如,我使用了您的模型,但将 id 更改为
Guid
,只要您始终使用 guid 作为标识符,它就应该有效。
var feed = container
.GetItemLinqQueryable<Outer>()
.SelectMany(t => t.Middles.Select(m => new { t, m }))
.SelectMany(x => x.m.Inners.Select(i => new { x.t, x.m, i }))
.Where(x => x.i.Secret == "Forbidden")
.Select(x => new
{
BottomId = x.i.id,
MiddleId = x.m.id,
TopId = x.t.id,
})
.ToFeedIterator();
List<ResultRecord> results = [];
while (feed.HasMoreResults)
{
foreach (var item in await feed.ReadNextAsync())
{
results.Add(new ResultRecord(item.TopId, item.MiddleId, item.BottomId));
}
}