使用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
相关产品推荐
相关产品推荐

