我一直在关注Logging in ASP.NET Core,它工作正常。
我对此行有疑问
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
我想知道为什么他们不使用$ - string interpolation?
_logger.LogWarning(LoggingEvents.GetItemNotFound, $"GetById({ID}) NOT FOUND");
为什么LogWarning扩展名有一个params object[] args
参数?
什么都可以发送字符串消息呢?
我认为这是有原因的,但是我无法在任何地方找到解释。我想知道我应该使用哪种方法才能正确登录.net核心。
答案 0 :(得分:6)
至少有两个原因。
首先,记录在字符串内插之前,并且Microsoft尚未发明时间机器。字符串插值仅在2015年7月的C#6中引入,但是日志记录方法遵循自{.1}以来dotnet framework 2.0使用的模式。
第二,性能。如果使用字符串插值并且将字符串作为参数传递,则在调用Microsoft.Build.Utilities
之前进行插值。但是,并非每次对Log的调用都会导致记录某些内容-这取决于配置。
如果您以Log
级别登录某项并且当前配置为DEBUG
级别,则浪费时间进行字符串插值,您可以说“谢谢,但是不,谢谢” ,并且对参数不执行任何操作后立即返回。
扩展第二,性能 在内部,大多数记录器基本上是这样的:
INFORMATION
因此,如果未启用调试,则插值操作将减少一遍。
答案 1 :(得分:4)
我怀疑这个问题可以改写为:
为什么它们不提供接受FormattableString的重载,以使用字符串插值语法传递消息模板和参数,就像EF Core用于参数化查询一样?
我会说他们做对了。在此时,使用FormattableString的 带来的好处很小,但会造成很多混乱。
我只是发现Serilog's author explains why this isn't such a good idea,即使语义记录库看起来很适合这种情况
语义记录
有人可以说FormattableString
是Serilog之类的语义日志记录库的重要补充。在这种情况下,内插字符串确实会丢失重要信息。
通话
Log.Information("Logged in {UserId}", loggedInUserId);
不仅会记录基于模板的字符串,还会保留参数的名称和值,并将其提供给过滤器和目标。用:取得相同的结果不是很好吗?
Log.Information($"Logged in {loggedInUserId}");
Serilog's author doesn't think so并说明:
Log.Information($"Enabling categories {new[]{1, 2, 3}}");
并得出结论
字符串插值是一个很棒的功能,我很期待C#很久了。为Serilog提供直接支持的想法非常有趣,值得探讨,但我越来越相信这是不必要的。
当插值保持代码DRY时,插值非常好,可以消除{0}和{1}的多余杂波,并防止参数不匹配。
对于Serilog,我认为将{UserId}之类的属性名称视为冗余是不正确的;在实施良好的日志记录策略中,它们是图片中非常重要的一部分,值得自己考虑。您不会让变量名确定关系数据库中的表名和列名–在这里要考虑的折衷点完全相同。
原始解释
实际上,这是EF Core最具争议的功能之一,很容易导致人们希望通过使用参数避免SQL注入和转换问题。
此电话:
string city = "London";
var londonCustomers = context.Customers
.FromSql($"SELECT * FROM Customers WHERE City = {city}");
调用FromSql(FormattableString)
并创建一个参数化查询:
SELECT * FROM Customers WHERE City = @p0
并传递London
作为参数值。
另一方面:
string city = "London";
var query=$"SELECT * FROM Customers WHERE City = {city}";
var londonCustomers = context.Customers.FromSql(query);
呼叫FromSql(string)
并将生成:
SELECT * FROM Customers WHERE City = London
哪个无效。即使您知道知道这种风险,也常常陷入这种陷阱。
当您已经有了预定义的查询或消息时,它根本没有帮助。这种用法在日志记录中更为常见,在日志记录中,您(应该)使用在众所周知的位置定义的特定消息模板,而不是在每个日志位置都散布相似的外观字符串。
有人可能会说this addition made EF Core 2.0 somewhat safer是因为人们已经开始在EF Core 1.0中使用字符串插值,从而导致无效查询。添加FormattableString
超载后,EF Core团队可以缓解那个情况,同时更容易意外导致其他问题。
此时,测井设计师决定避免这种混乱。记录原始字符串不会带来如此灾难性的后果。