EF Core执行DbCommand报错:参数@p8 Size=-1与配置不符
问题场景
使用Microsoft.EntityFrameworkCore向数据库插入数据时触发Failed executing DbCommand错误,排查发现对应[Pel].[DemandeInterventions]表[Etat]字段的参数@p8 Size被设为-1,但该字段在EF中已配置MaxLength=75,数据库列类型为nvarchar(75),其余参数Size均正常匹配配置值。
错误日志
[2022-11-01 00:13:30.381 -04:00] [Error] [AC-PEL1:73] [Microsoft.EntityFrameworkCore.Database.Command] Failed executing DbCommand ("13"ms) [Parameters=["@p0='?' (Size = 10), @p1='?' (DbType = DateTime2), @p2='?' (DbType = DateTime2), @p3='?' (DbType = DateTime2), @p4='?' (DbType = DateTime2), @p5='?' (DbType = DateTime2), @p6='?' (Size = 100), @p7='?' (DbType = Guid), @p8='?' (Size = -1) , @p9='?' (DbType = Int32), @p10='?' (Size = 100), @p11='?' (DbType = Boolean), @p12='?' (Size = 2000), @p13='?' (Size = 100), @p14='?' (Size = 2000), @p15='?' (Size = 2000), @p16='?' (Size = 2000)"], CommandType='Text', CommandTimeout='30']
执行的SQL语句
SET NOCOUNT ON; INSERT INTO [Pel].[DemandeInterventions] ([CodeIntervention], [DateCourriel], [DateDerniereModifExterne], [DateEffectuee], [DateIntervention], [DatePrevue], [Description], [EmailId], [Etat], [IdDemande], [IntervenantExterne], [InterventionExterne], [MessageCourriel], [NomEmploye], [NoteClient], [NoteCourriel], [NoteInterne]) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16); SELECT [Id] FROM [Pel].[DemandeInterventions] WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();
解决方案
1. 确认实体配置的准确性
先检查DemandeIntervention实体的配置是否正确,确保MaxLength约束确实生效:
- 使用DataAnnotations:
public class DemandeIntervention { // 其他属性... [MaxLength(75)] public string Etat { get; set; } } - 使用Fluent API:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<DemandeIntervention>() .Property(d => d.Etat) .HasMaxLength(75) .HasColumnType("nvarchar(75)"); // 显式指定列类型,确保和数据库一致 }
2. 升级EF Core版本
部分旧版本的EF Core存在参数大小推断的bug,建议升级到当前使用分支的最新补丁版本(比如3.x、5.x、6.x的最新稳定版),新版本通常会修复这类映射问题。
3. 用拦截器强制修正参数大小
如果以上方法都无效,可以通过EF Core拦截器在命令执行前修改参数Size:
- 定义拦截器:
public class ParameterSizeFixInterceptor : DbCommandInterceptor { public override InterceptionResult<DbDataReader> ReaderExecuting( DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result) { foreach (DbParameter param in command.Parameters) { // 匹配目标参数,也可根据参数对应字段名判断,提升通用性 if (param.ParameterName == "@p8" && param.Size == -1) { param.Size = 75; } } return base.ReaderExecuting(command, eventData, result); } } - 在DbContext中注册拦截器:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.AddInterceptors(new ParameterSizeFixInterceptor()); // 其他数据库配置... }
验证方法
修改后重新执行插入操作,查看EF Core日志中@p8的Size是否变为75,确认错误是否消除。
内容的提问来源于stack exchange,提问作者Eric Caron

