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

能否将readonly struct用作Entity Framework Core的自有实体?

问题与解决方案

需求

想用Password只读结构体替代User类中的PasswordHash和PasswordSalt两个属性,要求这两个值仍作为用户表的独立列存储,同时保证更新密码时必须同时修改Hash和Salt(为了代码抽象与简洁)。

现有代码

User实体类

public class User
{
    /* 其他属性 */

    public Password Password { get; set; }
}

Password只读结构体

public readonly struct Password
    : IEquatable<Password>
{
    public string Hash { get; }
    public string Salt { get; }

    public Password(string hash, string salt)
    {
        Hash = hash;
        Salt = salt;
    }

    public bool Equals(Password other)
    {
        return Hash == other.Hash && Salt == other.Salt;
    }

    public override bool Equals(object? obj)
    {
        return obj is Password other && Equals(other);
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(Hash, Salt);
    }

    public static bool operator ==(Password left, Password right) => left.Equals(right);
    public static bool operator !=(Password left, Password right) => !left.Equals(right);
}

已知可行但不符合需求的方式

用记录类型可以实现映射,但无法满足“只读属性强制同时更新”的要求:

public record Password(string Hash, string Salt);

正确实现方式(你尝试的OwnsOne配置是有效的)

你用OwnsOne的配置思路完全正确,只需要确认几个前提:

  1. 使用EF Core 2.0及以上版本(值对象映射从该版本开始支持)
  2. User类的Password属性保留set访问器(当前代码已满足)

最终的OnModelCreating配置如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>(entity =>
    {
        entity.OwnsOne(u => u.Password, navBuilder =>
        {
            navBuilder.Property(p => p.Hash).HasColumnName("PasswordHash");
            navBuilder.Property(p => p.Salt).HasColumnName("PasswordSalt");
        });
    });

    base.OnModelCreating(modelBuilder);
}

密码更新方式

因为Password是只读结构体,无法单独修改其Hash或Salt属性,必须创建新实例赋值,刚好满足“同时修改Hash和Salt”的需求:

// 正确的更新方式
user.Password = new Password(newHashedPassword, newSalt);

这样EF Core会自动将Password.Hash映射到数据库的PasswordHash列,Password.Salt映射到PasswordSalt列,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 05:33:35