You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Entity Framework自定义ModelBuilder调用UseModel时创建异常排查

Fixing "Property could not be mapped" Error in Sqlite In-Memory Unit Tests

Let me break down what's likely happening here and how to fix it:

First off, that error about AppUser.AvatarImage (a string type) not being mapped is a huge clue—EF Core does support string as a primitive type, so this almost always means your test's model configuration isn't matching what your production AppDbContext uses. Here's how to troubleshoot and fix it:

1. Check for Missing Configuration in Your Test Setup

Take a look back at your original AppDbContext.OnModelCreating method. Chances are, there's code handling AppUser.AvatarImage that you didn't replicate in your test's manual ModelBuilder setup. For example:

// Original OnModelCreating might have something like this
modelBuilder.Entity<AppUser>()
    .Ignore(u => u.AvatarImage); // Or some explicit mapping configuration

If this code exists in production but not in your test, EF Core will treat AvatarImage as a regular entity property and fail to map it (even though it's a string) because it's missing that critical configuration step.

2. Ensure All Configuration Classes Are Loaded

When you call ApplyConfigurationsFromAssembly in your test, double-check that:

  • Your AppUser configuration class (e.g., AppUserConfiguration) inherits from IEntityTypeConfiguration<AppUser>
  • The configuration class is in the same assembly as your other entity configurations (or you're explicitly passing the correct assembly to the method)
  • The configuration class has a public access modifier (EF Core can't discover internal/private configuration classes)

3. Unify Configuration Logic to Avoid Drift

The best way to prevent this kind of mismatch is to extract your shared model configuration into a reusable extension method, so both production and test code use the exact same setup. Here's how:

Create a static extension class:

public static class ModelBuilderExtensions
{
    public static void ConfigureApplicationModels(this ModelBuilder modelBuilder)
    {
        // Load all entity configurations from the assembly
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
        
        // Add your Tenant.Profile JSON conversion logic
        modelBuilder.Entity<Tenant>()
            .Property(t => t.Profile)
            .HasConversion(
                v => JsonSerializer.Serialize(v, null),
                v => JsonSerializer.Deserialize<ProfileType>(v, null));
        
        // Add any other global configuration from your original OnModelCreating here
    }
}

Update your production AppDbContext to use this extension:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.ConfigureApplicationModels();
}

Then use the same extension in your test setup:

// In TestWithSqlite.cs
var modelBuilder = new ModelBuilder();
modelBuilder.ConfigureApplicationModels(); // Reuse the exact same logic
var model = modelBuilder.Model;

var options = new DbContextOptionsBuilder<AppDbContext>()
    .UseSqlite("DataSource=:memory:")
    .UseModel(model)
    .Options;

4. Simplify Your Test Setup (Alternative Approach)

If you don't need to manually build the model for your test, you can skip the UseModel step entirely and let the context handle configuration naturally. This is often simpler for unit tests:

var options = new DbContextOptionsBuilder<AppDbContext>()
    .UseSqlite("DataSource=:memory:")
    .Options;

using var context = new AppDbContext(options);
context.Database.OpenConnection(); // Required for in-memory Sqlite
context.Database.EnsureCreated();

This way, the context will run its full OnModelCreating logic automatically, so you don't have to worry about missing configuration steps.

Content的提问来源于stack exchange,提问作者Yasir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:21:00