C# 在生产源代码中将实体框架日志设置为调试窗口可以吗?

C# 在生产源代码中将实体框架日志设置为调试窗口可以吗?,c#,entity-framework,logging,visual-studio-debugging,C#,Entity Framework,Logging,Visual Studio Debugging,在生产源代码中使用这一行可以吗?它会产生什么样的性能惩罚?我知道Debug.WriteLine不会发送到使用版本配置构建的程序集 ddiCatalogEntities.Database.Log = msg => Debug.WriteLine(msg); 在调试模式下运行时,此行应将实体框架日志输出记录到VisualStudio调试控制台 #if DEBUG ddiCatalogEntities.Database.Log = msg => Debug.WriteLine(msg)

在生产源代码中使用这一行可以吗?它会产生什么样的性能惩罚?我知道Debug.WriteLine不会发送到使用版本配置构建的程序集

ddiCatalogEntities.Database.Log = msg => Debug.WriteLine(msg);
在调试模式下运行时,此行应将实体框架日志输出记录到VisualStudio调试控制台

#if DEBUG 
ddiCatalogEntities.Database.Log = msg => Debug.WriteLine(msg);
#endif

您喜欢上面的解决方案吗?

调试类的成员用ConditionalAttribute标记,因此如果您使用发行版配置,则不会编译它们。

首先,请注意,您不能将普通委托指向具有
ConditionalAttribute
的方法

但是,您使用的是lambda,因此编译正常。但它实际上编译成什么呢

考虑以下代码:

Action<string> print = message => Debug.WriteLine(message);
print("TEST");
Action print=message=>Debug.WriteLine(message);
打印(“测试”);
对于调试生成,此编译为:

Action<string> print = delegate (string message) {
    Debug.WriteLine(message);
};
print("TEST");
Action<string> print = delegate (string message) {
};
print("TEST");
Action print=delegate(字符串消息){
Debug.WriteLine(消息);
};
打印(“测试”);
对于发布版本,它编译为:

Action<string> print = delegate (string message) {
    Debug.WriteLine(message);
};
print("TEST");
Action<string> print = delegate (string message) {
};
print("TEST");
Action print=delegate(字符串消息){
};
打印(“测试”);
在这两种情况下,都会创建和调用一个委托-因此,在这两种情况下,都会有委托创建和调用的开销(参数被推送到堆栈上),即使发布版本实际上没有做任何事情

因此,对于您的情况,使用
#if DEBUG
与否的区别如下:

  • 如果使用
    #如果调试
    ,则根本没有开销,并且不会设置
    日志
    属性
  • 否则,您将需要设置
    Log
    属性,然后在调用该属性时不执行任何操作
在许多情况下,开销很小,您不介意,而且确保
Log
属性始终设置为某个值(默认为“不做任何事情”委托)也很好,这样您就不需要在每次引用它之前检查它是否为null

另一方面,使用
#if DEBUG
可以更清楚地了解正在发生的事情。lambda和使用
ConditionalAttribute
定义的方法的交互方式并不完全明显


所有这些都是一种迂回的说法:权衡利弊,做出自己的选择

我的同事建议使用.NETReflector,或者只是反编译和反编译发布和调试程序集。它证明了@Matthew Watson在这里所说的话。就我个人而言,我会说#如果调试对op的示例更好,仅仅因为如果.Log委托设置为null,那么EF(至少6)将不会经历准备日志语句的开销,它将完全删除日志格式化程序拦截器。如果您向它抛出一个空委托,那么现在您已经让它执行了一系列字符串操作,而这些操作在任何地方都不会被实际写入。