首页 > 解决方案 > MongoDocument 对象在查询时仅被部分填充

问题描述

我有一组用户正在尝试从数据库中读取,但由于某种原因,发生了一些我无法弄清楚的奇怪行为。希望有人可以建议或帮助我找到这个问题的根源。

所以基本上,每当我在 HomeController.cs 中调用这段代码时,会发生什么:

var users = await _database.GetCollection<User>("ApplicationUsers").FindAsync(_ => true);
var userList = users.ToList();

它只填充 userList 部分,这意味着只有 ID 和 ConcurrencyStamp 属性被填充,但其他属性总是最终为空(见:https ://i.imgur.com/RTF8ljL.png )

但是每当我在 Startup.cs 中的数据库连接初始化之后添加这一行时:

database.GetCollection<User>("ApplicationUsers");

然后突然 userList 确实填充了所有其他信息(如 https://i.imgur.com/f5IV7fh.png所示)

所以为了让它工作,我必须在连接初始化后立即获取集合,我不太喜欢,因为我不必为其他集合执行此操作。所以我的 mongo 连接代码在 Startup.cs 中必须如下所示:

var mongoUrl = new MongoUrl(config.GetSection("DatabaseSettings:ConnectionString").Value);

var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
mongoClientSettings.ClusterConfigurator = cb => ConfigureCluster(cb);

var client = new MongoClient(mongoClientSettings);
var database = client.GetDatabase(config.GetSection("DatabaseSettings:DatabaseName").Value);
database.GetCollection<User>("ApplicationUsers"); // TODO: This is needed just to let Mongo Driver know to which class to deserialize this collection

services.AddSingleton<IMongoDatabase>(database);

var pack = new ConventionPack()
{
    new CamelCaseElementNameConvention(),
    new IgnoreExtraElementsConvention(true),
    new DictionaryRepresentationConvention(DictionaryRepresentation.ArrayOfArrays)
};

ConventionRegistry.Register("DatabaseConventions", pack, t => true);

我猜在 Startup.cs 和 HomeController.cs 的执行之间发生了导致反序列化混乱的事情?

更新:

同样的行为似乎发生在一个干净的项目上,我安装的唯一 nuget 包是官方的 mongodb 驱动程序和 Matteo Fabbri 的 AspNetCore.Identity.Mongo。当我将 getCollection 用于其他类时,不会发生这种奇怪的反序列化行为。问题在于从 MongoUser 扩展的 ApplicationUser (由 AspNetCore.Identity.Mongo 库提供的类)

更新 2:

原来 AspNetCore.Identity.Mongo 库中的 MongoUser 类对注册的 ConventionPack 过敏。我通过在注册数据库约定之前和之后获取集合来测试这一点。现在为此寻找合适的解决方案。

更新 3:

我还发现文档是用大驼峰大小写命名的属性保存的,这可能是 mongodb 驱动程序混乱的原因。对于这个特定的类(ApplicationUser),似乎将它们保存在 CamelCase 中的约定被忽略了。

标签: c#mongodbasp.net-core

解决方案


我设法解决了这个问题。问题是代码执行的顺序。约定包在 MongoIdentity 之后注册并初始化数据库。在初始化 MongoIdentity 和数据库期间,ApplicationUser 被配置为在包中没有 CamelCaseElementNameConvention,这导致类被保存在 UpperCamelCase 中,因此在注册的 ConventionPack 处于活动状态时检索集合时会导致混乱。

对于那些在你认为你的代码应该可以工作的奇怪行为中挣扎的人,请记住代码执行的顺序非常重要,并且很可能是导致该行为的原因。祝大家好运!


推荐阅读