Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Line of code not working unless stepped through using breakpoint

The only thing I can think of is a race condition but both the calling function and the line of code are synchronous to my knowledge.

/// <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();
}

The line propInfo.SetValue(obj, null) will execute if I just breakpoint before the loop and step through one-by-one (or just break on that line) however if I don't use a breakpoint it never sets the property(ies) to null. Why is this?

Specific Details:

  • If I don't use a breakpoint it doesn't work.
  • If I place a breakpoint at the top of the foreach and hit f5 it doesn't work.
  • If I place a breakpoint at the top of the foreach and step-through via f10 it does work.
  • If I place a breakpoint on the line of code propInfo.SetValue(obj, null); it does work.
  • A breakpoint after the loop still shows the values as not null.
  • If I change null to 5 (which isn't a valid value) it throws an exception telling my that it's not a valid value.

To clarify, "Doesn't work" means that it doesn't set the property to null.

What I've tried:

  • Restarting Visual Studio (2013)
  • Changing the line of code (Used to be default(T))
  • Project Properties -> Build -> Optimize Code (initially off)

EDIT

It's been narrowed down that EF Navigation properties are the cause of this behavior. The code is running but for some reason the navigation properties refuse to become null. So what about navigation properties are causing this behavior?

like image 577
Shelby115 Avatar asked Oct 14 '15 18:10

Shelby115


People also ask

How do you run code until breakpoint?

Run to a breakpoint in code To set a simple breakpoint in your code, select the far-left margin next to the line of code where you want to suspend execution. You can also select the line and then select F9, select Debug > Toggle Breakpoint, or right-click and select Breakpoint > Insert Breakpoint.

Why breakpoint is not hitting with VS code?

If a source file has changed and the source no longer matches the code you're debugging, the debugger won't set breakpoints in the code by default. Normally, this problem happens when a source file is changed, but the source code wasn't rebuilt. To fix this issue, rebuild the project.

How do I skip a breakpoint in Visual Studio?

You can disable all breakpoints in one of the following ways: On the Debug menu, click Disable All Breakpoints. On the toolbar of the Breakpoints window, click the Disable All Breakpoints button.


2 Answers

Lazy-Loading

The navigation properties were lazy-loading, so when the serializer looked at them they got overwritten by the original value. So the setting of null was working the whole time but was getting overwritten by the lazy-loading.

Debugging

The reason the debugging appeared the way it did was because I was looking at the value before I executed the SetValue line of code. This caused the navigation property to load the value before executing the line of code resulting in the null value not being overwritten.

Solution

foreach (var propInfo in virtualProperties)
{
    propInfo.GetValue(obj); // Trigger any navigation property to load.
    propInfo.SetValue(obj, null);
}
like image 54
Shelby115 Avatar answered Oct 10 '22 04:10

Shelby115


I had a VERY similar issue in a Many-to-many EF6 code first setup. In my Web API controller I had been setting an object's navigation property from values set from a DTO. One being passed into my repo, they properties weren't being updated because of the lazy loading, but in debug mode it would work if I stepped near that section of code. I ended up using:

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

This appears to be working so far.. Since my dbContext is being disposed per controller, I don't think it will be an issue.

like image 34
Patrick Michalina Avatar answered Oct 10 '22 04:10

Patrick Michalina