使用Serilog向SQL Server新增的Message等自定义列写入数据失败如何解决
问题原因
Message是Serilog的内置保留字段,默认存储的是调用日志方法(Fatal/Information等)时传入的消息模板渲染后的内容,你通过ForContext("Message", "Some Message")添加的同名自定义属性优先级低于内置字段,写入SQL Server时会被内置值覆盖,所以不会生效。- 你当前的日志调用写法存在参数不匹配问题:
Fatal("{StackTrace}", ex.Message, ex.StackTrace)的消息模板只声明了1个占位符{StackTrace},却传入了2个参数,最终内置的Message字段只会渲染输出第一个参数ex.Message的值,自然不会出现你想要的"Some Message"。
解决方法
方案1:直接使用内置Message字段(最简单,无需修改Serilog配置)
如果你表中的Message列就是要存储自定义的消息内容,直接把内容放到日志方法的消息模板参数位置即可,其他自定义列(比如LikeExpression、StackTrace)通过ForContext传入即可:
Log.ForContext("LikeExpression", ex.Message) .ForContext("StackTrace", ex.StackTrace) .Fatal("Some Message");
此时内置Message字段的值就是你传入的"Some Message",会直接写入对应列,LikeExpression和StackTrace作为自定义属性也会写入对应匹配的列。
方案2:配置列映射解决冲突(如果必须用ForContext传Message值)
如果你的业务逻辑要求必须通过ForContext传递Message的值,需要修改Serilog.Sinks.MSSqlServer的列配置,解除内置Message字段的默认映射,改为绑定你自定义的Message属性:
- 在配置Sink的
ColumnOptions时,移除内置Message的默认存储逻辑,添加自定义列映射:
var columnOptions = new ColumnOptions(); // 移除默认的Message内置列存储 columnOptions.Store.Remove(StandardColumn.Message); // 添加自定义Message列,绑定同名自定义属性 columnOptions.AdditionalColumns = new List<SqlColumn> { new SqlColumn("Message", SqlDbType.NVarChar, 4000), new SqlColumn("LikeExpression", SqlDbType.NVarChar, 1000), // 其他自定义列在这里添加 };
- 配置完成后你原来的
ForContext("Message", "xxx")写法就可以正常写入值到Message列。
内容的提问来源于stack exchange,提问作者hala tech
相关产品推荐
相关产品推荐

