MongoDB映射注册失败:ArgumentException(Class map未冻结)问题排查
Let's break down why you're hitting this error and how to fix it step by step.
What's Causing the Error?
This exception pops up because the MongoDB .NET Driver automatically creates and freezes a default class map for your Article entity once it's first used (e.g., when you query the collection). When you try to register a custom class map later via BsonClassMap.RegisterClassMap, the driver throws this error because the existing frozen map can't be modified.
Additionally, your Initialize method might be executing too late—after the driver has already initialized the default map for Article.
Step-by-Step Fixes
1. Call Initialize Early in Your App Lifecycle
You need to run your class map initialization before any MongoDB operations are performed. In an ASP.NET Core app, this means calling it in Program.cs right after setting up dependency injection but before configuring your MongoDB context:
var builder = WebApplication.CreateBuilder(args); // Register your services first (including IUnitOfWork) builder.Services.AddScoped<IUnitOfWork, YourUnitOfWorkImplementation>(); // Build a temporary service provider to get IUnitOfWork var serviceProvider = builder.Services.BuildServiceProvider(); var uow = serviceProvider.GetRequiredService<IUnitOfWork>(); // Initialize MongoDB class maps NOW YourNamespace.Initialize(uow); // Now configure your MongoDB context builder.Services.AddMongoDbContext<YourDbContext>(options => { options.ConnectionString = builder.Configuration.GetConnectionString("MongoDB"); }); // Rest of your app setup...
2. Fix the Class Map Registration Logic
Update your Initialize method to check if the class map is already registered (to avoid duplicate registrations) and explicitly control the freeze behavior:
public static void Initialize(IUnitOfWork uOw) { // Skip if the class map is already registered if (BsonClassMap.IsClassMapRegistered(typeof(Article))) return; BsonClassMap.RegisterClassMap<Article>(map => { map.AutoMap(); // Map the CreatedByUser property to the "CreatedByUserId" field in MongoDB map.MapProperty(x => x.CreatedByUser) .SetElementName("CreatedByUserId") .SetSerializer(new AppUserSerializer(uOw)); // Manually freeze the map once all configurations are done map.Freeze(); }); }
3. Fix a Critical Logic Error in AppUserSerializer
Your Deserialize method has a backwards condition—it only queries the user when userId is empty, which is wrong. Correct it to fetch the user when userId is valid:
public override ApplicationUser Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var userId = context.Reader.ReadString(); ApplicationUser user = null; // Query the user ONLY when userId is not null/empty if (!string.IsNullOrEmpty(userId)) { user = _uOw.Users.Get(u => u.Id == userId).FirstOrDefault(); } return user; }
Extra Notes
- Make sure your
ApplicationUserclass has proper BSON mapping configured (e.g.,[BsonId]on its Id property) so the driver can correctly retrieve it from your database. - If you're using dependency injection, ensure
IUnitOfWorkhas a compatible lifecycle (singleton or scoped, depending on how you use it) to avoid invalid service instances in the serializer.
内容的提问来源于stack exchange,提问作者twirk hacked

