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:
propInfo.SetValue(obj, null);
it does work.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:
default(T)
)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?
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.
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.
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.
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);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With