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

使用MongoDB EF Core调用FirstOrDefault时遇Expression Must be Writeable错误

EF Core搭配MongoDB调用FirstOrDefault时出现Expression must be writeable错误

问题场景

我使用Entity Framework Core搭配MongoDB,在调用FirstOrDefault方法时遇到错误。

基类定义:

public class SignInCredentials(string username, string? password)
{
    public string Username { get; set; } = username;
    public string? Password { get; protected init; } = password;
}

继承的Account类:

public class Account : SignInCredentials
{
    [Key]
    public ObjectId Id { get; private init; }

    private readonly byte[] salt;

    public Account(string username, string password) : base(username, null)
    {
        Id = new ObjectId();
        salt = GenerateSalt();
        Password = Hash(password, salt);
    }

    // 其他未展示代码
}

DbSet配置:

modelBuilder.Entity<Account>().ToCollection("accounts");

执行查询时出错:

accounts.FirstOrDefault(a => a.Username == creds.Username); // creds是SignInCredentials实例

错误信息:

System.ArgumentException: Expression must be writeable (Parameter 'left')
         at System.Linq.Expressions.Expression.RequiresCanWrite(Expression expression, String paramName)
         at System.Linq.Expressions.Expression.Assign(Expression left, Expression right)
         at System.Linq.Expressions.Expression.MakeBinary(ExpressionType binaryType, Expression left, Expression right, Boolean liftToNull, MethodInfo method, LambdaExpression conversion)
         at System.Linq.Expressions.BinaryExpression.Update(Expression left, LambdaExpression conversion, Expression right)
         at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
         at MongoDB.EntityFrameworkCore.Query.Visitors.ProjectionBindingRemovingExpressionVisitor.VisitBinary(BinaryExpression binaryExpression)

修复方案

方案1:修改基类属性为init-only

问题根源是EF Core MongoDB的查询翻译器在处理继承类的可写属性(get; set;)时,错误地尝试生成赋值表达式。将基类的Username改为get; init;即可避免这个问题:

public class SignInCredentials(string username, string? password)
{
    public string Username { get; init; } = username; // 替换set为init
    public string? Password { get; protected init; } = password;
}

init修饰符允许在对象构造时赋值,同时保证属性在构造后不可修改,完全符合账户用户名的业务逻辑,也能让EF Core正确处理查询表达式。

方案2:升级EF Core MongoDB驱动版本

如果必须保留set修饰符,检查当前使用的MongoDB.EntityFrameworkCore版本是否存在已知bug。升级到最新稳定版(如8.x系列)可能已经修复了这个查询翻译的问题。

方案3:显式配置实体继承映射

在EF Core模型配置中,显式指定基类的属性映射,帮助驱动正确识别继承关系:

modelBuilder.Entity<Account>(b =>
{
    b.ToCollection("accounts");
    // 显式映射基类属性
    b.Property(a => a.Username).IsRequired();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:15:25