除非逐步使用断点,否则代码行不起作用

时间:2015-10-14 18:34:30

标签: c# entity-framework entity-framework-6

我唯一能想到的是竞争条件,但是调用函数和代码行都与我的知识同步。

/// <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)为null。这是为什么?

具体细节

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

澄清一下,“不起作用”表示它不会将该属性设置为null。

我尝试了什么:

  • 重新启动Visual Studio(2013)
  • 更改代码行(以前为default(T)
  • 项目属性 - &gt;构建 - &gt;优化代码(最初关闭)

修改

已经缩小了EF导航属性是导致此行为的原因。代码正在运行但由于某种原因导航属性拒绝变为null。那么导航属性会导致这种行为呢?

2 个答案:

答案 0 :(得分:5)

<强>延迟加载

导航属性是延迟加载的,因此当序列化程序查看它们时,它们会被原始值覆盖。所以null的设置一直在工作,但是被延迟加载覆盖了。

<强>调试

调试以它的方式出现的原因是因为我在执行SetValue代码行之前查看了该值。这导致导航属性在执行代码行之前加载值,导致空值不被覆盖。

<强>解决方案

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

答案 1 :(得分:0)

我在多对多EF6代码首次设置中遇到了类似的问题。在我的Web API控制器中,我一直在从DTO设置的值设置对象的导航属性。一个被传递到我的仓库,他们的属性没有因为延迟加载而被更新,但是在调试模式下,如果我走近那段代码,它将会工作。我最终使用了:

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

这似乎到目前为止工作..因为我的dbContext是按控制器处理的,所以我不认为这是一个问题。