2015-10-14 72 views
7

我能想到的唯一的事情是竞争条件,但调用函数和代码行是我的知识同步。行代码不工作,除非通过使用断点逐步

/// <summary> 
/// Gets the log format string for an info-level log. 
/// </summary> 
public static string Info<T>(string action, T obj) 
{ 
    var stringBuilder = new StringBuilder(String.Format(
     "Action: {0} \tObject: {1} \tUser: {2} \tJson: ", 
     action, typeof(T).Name, User 
    )); 

    // Set all virtual properties to null. This should stop circular references of navigation properties. 
    var virtualProperties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(x => x.GetSetMethod().IsVirtual && !x.PropertyType.IsPrimitive); 
    foreach (var propInfo in virtualProperties) 
    { 
     propInfo.SetValue(obj, null); // This Line is the culprit. 
    } 

    GetJsonSerializer().Serialize(obj, stringBuilder); 

    return stringBuilder.ToString(); 
} 

propInfo.SetValue(obj, null)如果我在循环之前刚刚断点,并通过一个接一个步骤(或只在该行打破)将执行但是如果我不使用断点它从来没有设置该属性的线( ies)为空。为什么是这样?

具体细节

  • 如果我不使用断点这是行不通的。
  • 如果我在foreach的顶部放置一个断点并按f5,它不起作用。
  • 如果我在foreach的顶部放置一个断点并通过f10执行,它确实有效。
  • 如果我在代码行propInfo.SetValue(obj, null);上放置一个断点,它确实有效。
  • 循环后的断点仍显示为非空值。
  • 如果我将null更改为5(这不是有效值),它会引发异常,告诉我它不是有效值。

澄清,“不起作用”意味着它不会将该属性设置为null。

我已经试过什么:

  • 重新启动Visual Studio中(2013年)
  • 改变的代码行(以前是default(T)
  • 项目属性 - >建设 - >优化代码(最初关闭)

EDIT

已经缩小了EF导航属性是导致此行为的原因。代码正在运行,但由于某些原因导航属性拒绝成为空。那么导航属性如何导致这种行为?

+0

发生什么事了,如果在传入之前有任何东西需要obj? – lintmouse

+0

我正在提交它进行编辑。它通过EF保存到数据库。然后我通过它来序列化和记录。在这种情况下,我无法想象任何事情会影响它,但我认为任何事情都是可能的。在此功能之后,log4net将日志条目保存到数据库。 – Shelby115

+0

如果您尝试非EF'T'类型,会发生什么?也许有可能实体框架不是“接受”财产变化,我们可能能够确定这个原因。 – 31eee384

回答

5

延迟加载

导航性能是延迟加载,所以当串行看着他们,他们得到了由原始值覆盖。所以null的设置一直在工作,但被延迟加载覆盖。

调试

原因调试出现它确实是因为我一直在寻找的价值之前,我执行的代码的SetValue线的方式。这导致导航属性在执行代码行之前加载该值,导致空值不被覆盖。

解决方案

foreach (var propInfo in virtualProperties) 
{ 
    propInfo.GetValue(obj); // Trigger any navigation property to load. 
    propInfo.SetValue(obj, null); 
} 
+0

只是好奇,将添加一个.All()或.ToList()选择器到typeof(T).GetProperties(...)的末尾强制集合枚举和加载所有项目? –

+0

'.ToList()'添加到'typeof(T).GetProperties()...'不会强制加载。这是因为这是属性集合而不是属性本身。我测试证实我的怀疑。 – Shelby115

0

我在许多一对多EF6代码首先设置有一个非常类似的问题。在我的Web API控制器中,我从根据DTO设置的值设置对象的导航属性。一个被传入我的回购,他们的属性没有被更新,因为延迟加载,但在调试模式下,它会工作,如果我走近附近的代码段。我最终使用:

try { 
    TheDatabase.Configuration.LazyLoadingEnabled = false; 
    ... 
    ... 
} 
finally { 
    TheDatabase.Configuration.LazyLoadingEnabled = true; 
} 

这似乎到目前为止奏效。由于我的DbContext被配置成在每个控制器,我不认为这会是一个问题。