-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default to using entityType for incomplete serializationInfo. #2279
Conversation
a703224
to
3dd19f2
Compare
3dd19f2
to
a00e0a8
Compare
# Conflicts: # src/Microsoft.OData.Core/ODataWriterCore.cs
ddc5b50
to
db2940e
Compare
KeyValuePair<string, object>[] keyProperties = null; | ||
string actualEntityTypeName = null; | ||
string actualEntityTypeName = resource.TypeName ?? actualEntityType?.FullName(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know how important the old check for empty string is? We are missing that now, maybe this should be string.IsNullOrEmpty(resource.TypeName) ? actualEntityType?.FullName() : resource.TypeName
#Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is unlikely this will be an empty string, but I like the robustness of your suggestion and will adopt it.
|
||
for (int keyProperty = 0; keyProperty < keyProperties.Length; keyProperty++) | ||
{ | ||
if (keyProperties[keyProperty].Value == null || (keyProperties[keyProperty].Value is ODataValue && !(keyProperties[keyProperty].Value is ODataEnumValue))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears that the compiler is not smart enough to optimize the multiple indexing operations (probably because nothing guarantees that there are no side effects):
Multiple indexes
Storing the indexed value
In the first example, the IL indicates that the indexing is performed a second time for the WriteLine
call. The JITer might be able to optimize this, but there's really no way to know for sure. It would probably make the most sense to store keyProperties[keyProperty]
in a variable scoped to the loop so that we only index the one time, instead of 4 times.
#Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch -- thanks!
{ | ||
this.keyProperties = Enumerable.Empty<KeyValuePair<string, object>>().ToArray(); | ||
return Enumerable.Empty<KeyValuePair<string, object>>().ToArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not worth it as part of this change, but this will allocate a new array every time we return, even though all 0-length arrays are the same (we actually get warnings from the compiler for this). We could avoid unnecessary allocations and garbage collection with this small class:
public static class Array
{
public static T[] Empty<T>()
{
return Internal<T>.Empty;
}
private static class Internal<T>
{
public static T[] Empty = new T[0];
}
}
New versions of .NET already have these singletons, but for back-compat we could write this one ourselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes; I tried to use Array.Empty(), but discovered it wasn't supported in .net45, so left it as it was. I agree we should go through and optimize everywhere we return empty arrays.
if (EdmExtensionMethods.HasKey(this.CurrentScope.NavigationSource, this.CurrentScope.ResourceType as IEdmStructuredType)) | ||
IEdmEntityType currentEntityType = this.CurrentScope.ResourceType as IEdmEntityType; | ||
ODataResourceBase resource = this.CurrentScope.Item as ODataResourceBase; | ||
KeyValuePair<string, object>[] keys = ODataResourceMetadataContext.GetKeyProperties(resource, null, currentEntityType, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetKeyProperties
seems to make the assumption that resource
isn't null
. I know that this isn't really related to your change, but not validating that currentEntityType
is actually a IEdmEntityType
means we could get a NullReferenceException
here. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is our code and should never be called with a null resource. I added an assert to GetKeyProperties.
model.AddElements(new IEdmSchemaElement[] { entityType, nestedEntityType, container }); | ||
|
||
// setup writer | ||
var stream = new MemoryStream(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MemoryStream
implements IDisposable
. Please wrap it in a using
block #Resolved
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
Issues
This pull request fixes #2278
Description
ODL expects that, if you set SerializationInfo on the resource then you are taking responsibility for providing all of the information necessary for serialization.
When ODL tries to get key properties in order to append the key segment, it checks to see if the serializationInfo for the resource is null -- if so, it uses the model to determine key properties and all is good. On the other hand, if serializationInfo on the resource is non-null then it looks for properties whose serializationInfo identify them as key properties. Finding none, it errors.
This change makes ODL more robust by falling back to using the entityType to identify key properties if the resource has serializationInfo but none of the properties have serializationInfo that identifies them as key properties.
Checklist (Uncheck if it is not completed)
Additional work necessary
None