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

如何配置Entity Framework Core以支持自定义值对象类型?

问题:EF Core 配置自定义值对象类型的属性

我尝试创建迁移,但不知道如何配置Entity Framework以支持带有自定义类型的属性。

我的值对象BrandName类:

public class BrandName : ValueObject<BrandName>
{
    public string Value { get; }

    private BrandName(string name)
    {
        Value = name;
    }

    public static Result<BrandName> Create(string brandName) 
    {
        brandName = (brandName ?? string.Empty).Trim();

        if (String.IsNullOrEmpty(brandName)) 
        {
            return Result.Fail<BrandName>(BrandValidationValues.BrandNameEmpty);
        }

        if (brandName.Length > BrandValidationValues.BrandNameLength) 
        {
            return Result.Fail<BrandName>(BrandValidationValues.BrandNameTooLong);
        }

        return Result.Ok(new BrandName(brandName));
    }

    protected override bool EqualsCore(BrandName other)
    {
        return Value.Equals(other.Value, StringComparison.InvariantCultureIgnoreCase);
    }

    protected override int GetHashCodeCore()
    {
        return Value.GetHashCode();
    }

    public static implicit operator string(BrandName brandName)
    {
        return brandName.Value;
    }

    public static explicit operator BrandName(string brandName)
    {
        return Create(brandName).Value;
    }
}

我的实体CatalogBrand类:

public class CatalogBrand : Entity
{
    private string _name;

    public virtual BrandName Name
    {
        get => (BrandName)_name;
        set => _name = value;
    }
}

Entity Framework配置:

class BrandEntityTypeConfiguration
: IEntityTypeConfiguration<CatalogBrand>
{
    public void Configure(EntityTypeBuilder<CatalogBrand> builder)
    {
        builder.ToTable("Brand");

        builder.HasKey(ci => ci.Id);

        builder.Property(ci => ci.Id)
            .UseHiLo("brand_hilo")
            .IsRequired();

        builder.Property(cb => cb.Name)
            .IsRequired()
            .HasMaxLength(100);
    }
}

遇到的错误:

属性'CatalogBrand.Name'的类型为'BrandName',当前数据库提供程序不支持该类型。请更改属性CLR类型,或使用'[NotMapped]'特性,或在'OnModelCreating'中使用'EntityTypeBuilder.Ignore'忽略该属性。


解决方案

EF Core 默认不识别自定义值对象类型,可通过以下两种方案解决:

方案1:使用值转换映射字符串类型

修改BrandEntityTypeConfiguration配置,为Name属性添加值转换逻辑,实现BrandName与string的双向转换:

class BrandEntityTypeConfiguration : IEntityTypeConfiguration<CatalogBrand>
{
    public void Configure(EntityTypeBuilder<CatalogBrand> builder)
    {
        builder.ToTable("Brand");

        builder.HasKey(ci => ci.Id);

        builder.Property(ci => ci.Id)
            .UseHiLo("brand_hilo")
            .IsRequired();

        // 配置值转换:BrandName <-> string
        builder.Property(cb => cb.Name)
            .IsRequired()
            .HasMaxLength(100)
            .HasConversion(
                // 写入数据库时,将BrandName转为字符串
                brandName => brandName.Value,
                // 读取数据库时,将字符串转为BrandName实例
                dbValue => BrandName.Create(dbValue).Value
            );
    }
}

方案2:映射私有字段并忽略公开属性

直接映射实体的私有字段_name,同时标记公开的Name属性为不映射:

class BrandEntityTypeConfiguration : IEntityTypeConfiguration<CatalogBrand>
{
    public void Configure(EntityTypeBuilder<CatalogBrand> builder)
    {
        builder.ToTable("Brand");

        builder.HasKey(ci => ci.Id);

        builder.Property(ci => ci.Id)
            .UseHiLo("brand_hilo")
            .IsRequired();

        // 映射私有字段,指定数据库列名为Name
        builder.Property<string>("_name")
            .IsRequired()
            .HasMaxLength(100)
            .HasColumnName("Name");

        // 忽略公开的Name属性
        builder.Ignore(cb => cb.Name);
    }
}

注意事项

  • 方案1中使用BrandName.Create(dbValue).Value时,需确保数据库中的字符串符合校验规则,否则会抛出异常;如需容错,可在转换逻辑中添加错误处理。
  • 值转换功能支持EF Core 2.x及以上版本,低版本需自定义类型转换器。

内容的提问来源于stack exchange,提问作者Vlad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 07:09:11