This question is about this code:
entityEntry.Property("WhateverProperty").CurrentValue = 1;
I answered this question yesterday and if you notice in the comments to the question (not the answer), one of the members @gertarnold said this:
entityEntry.Property("InsertedBy") doesn't use reflection, it reads the EF metadata.
Sure it uses the EF metadata to figure out if the entity has that property but I am pretty sure somewhere down the line they would have to use reflection to set the property.
I tried looking at the source code here, here and here (line 484) and then chickened out.
So the questions are:
It does not use reflection (the reflection is done at the time metadata model is created), but one time built and cached delegate from compiled dynamic expression.
The code that does the actual property set is here:
internal static void SetValue(EdmProperty property, object target, object value)
{
var setter = GetSetterDelegateForProperty(property);
setter(target, value);
}
and building the expression and compiling the delegate is here.
Basically it creates, caches and uses something like this:
Action<object, object> setter = (target, value) =>
((TEntity)target).Property = (TValue)value;
EntitEntry.CurrentValue
ends up setting a property value in EdmProperty
by calling a compiled expression tree built once (when building the entity model, and then using reflection) and cached as Action
:
// <summary>
// cached dynamic method to set a CLR property value on a CLR instance
// </summary>
internal Action<object, object> ValueSetter
{
get { return _memberSetter; }
set
{
DebugCheck.NotNull(value);
// It doesn't matter which delegate wins, but only one should be jitted
Interlocked.CompareExchange(ref _memberSetter, value, null);
}
}
Setting a property by this method is roughly 8 times slower than directly setting it, but still a great deal faster than reflection, even when the PropertyInfo
is cached. This is demonstrated here. To summarize:
Writing a Property (‘Set’)
Method Mean
===========================================
SetViaProperty 1.4043 ns
SetViaDelegate 2.8215 ns
SetViaILEmit 2.8226 ns
SetViaCompiledExpressionTrees 10.7329 ns <=
SetViaFastMember 36.6210 ns
SetViaReflectionWithCaching 214.4321 ns
SetViaReflection 287.1039 ns
SetViaDelegateDynamicInvoke 922.4618 ns
So, as expected, EF uses the fastest possible method to set a property value in an object of which it has to determine the setter at runtime. The faster methods require compile-time knowledge of entity types or a third-party library.
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