Skip to content

Commit c42f50f

Browse files
committed
Squashing Commits
Squashing Commits Update DeltaOfTStructuralType.cs test change Update Microsoft.AspNetCore.OData.Test.csproj Update Microsoft.Test.E2E.AspNetCore3x.OData.csproj updates Update WebStack.versions.settings.targets Update WebStack.versions.settings.targets Update GetNugetPackageMetadata.proj Update WebStack.versions.settings.targets For testing update Update BulkInsertController.cs Updates updates updates Update NuGet.Config Update BulkOperationPatchHandlersEF.cs updates
1 parent 5d20b2d commit c42f50f

21 files changed

+552
-76
lines changed

src/Microsoft.AspNet.OData.Shared/DataModificationExceptionType.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public DataModificationExceptionType(DataModificationOperationKind failedOperati
6262
}
6363

6464
/// <summary>
65-
/// Represents king of <see cref="DataModificationOperationKind"/> type of operation
65+
/// Represents kind of <see cref="DataModificationOperationKind"/> type of operation
6666
/// </summary>
6767
public DataModificationOperationKind FailedOperation { get; }
6868

src/Microsoft.AspNet.OData.Shared/EdmChangedObjectCollection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ private void PatchItem(EdmStructuredObject changedObj, EdmStructuredObject origi
238238
/// <summary>
239239
/// This applies ODataId parsed Navigation paths, get the value identified by that and copy it on original object, for typeless entities
240240
/// </summary>
241-
private void ApplyODataId(ODataIdContainer container, EdmStructuredObject original, ODataEdmAPIHandlerFactory apiHandlerFactory)
241+
private void ApplyODataId(IODataIdContainer container, EdmStructuredObject original, ODataEdmAPIHandlerFactory apiHandlerFactory)
242242
{
243243
EdmODataAPIHandler edmApiHandler = apiHandlerFactory.GetHandler(container.ODataIdNavigationPath);
244244

src/Microsoft.AspNet.OData.Shared/EdmEntityObject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public EdmEntityObject(IEdmEntityType edmType, bool isNullable)
6464
/// <summary>
6565
/// Container to hold ODataId
6666
/// </summary>
67-
public ODataIdContainer ODataIdContainer { get; set; }
67+
public IODataIdContainer ODataIdContainer { get; set; }
6868

6969
/// <summary>
7070
/// DeltaKind as Entry

src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializer.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,8 @@ private static ODataPath GetODataPath(string id, ODataDeserializerContext readCo
569569
private static void ApplyODataIDContainer(object resource, ODataResourceWrapper resourceWrapper,
570570
ODataDeserializerContext readContext)
571571
{
572-
//if id null check, add delta case as well c
572+
//Setting Odataid , for POCO classes, as a property in the POCO object itself(if user has OdataIDContainer property),
573+
//for Delta and EdmEntity object setting as an added property ODataIdcontianer in those classes
573574
if (resourceWrapper.ResourceBase?.Id != null)
574575
{
575576
string odataId = resourceWrapper.ResourceBase.Id.OriginalString;
@@ -578,7 +579,7 @@ private static void ApplyODataIDContainer(object resource, ODataResourceWrapper
578579

579580
if (odataPath != null)
580581
{
581-
ODataIdContainer container = new ODataIdContainer();
582+
IODataIdContainer container = new ODataIdContainer();
582583

583584
NavigationPath navigationPath = new NavigationPath(odataId, odataPath.Segments);
584585
container.ODataIdNavigationPath = navigationPath;
@@ -593,10 +594,19 @@ private static void ApplyODataIDContainer(object resource, ODataResourceWrapper
593594
}
594595
else
595596
{
596-
PropertyInfo containerPropertyInfo = EdmLibHelpers.GetClrType(odataPath.EdmType, readContext.Model).GetProperties().Where(x => x.PropertyType == typeof(ODataIdContainer)).FirstOrDefault();
597+
PropertyInfo containerPropertyInfo = EdmLibHelpers.GetClrType(odataPath.EdmType, readContext.Model).GetProperties().Where(x => x.PropertyType == typeof(IODataIdContainer)).FirstOrDefault();
597598
if (containerPropertyInfo != null)
598599
{
599-
containerPropertyInfo.SetValue(resource, container);
600+
IODataIdContainer resourceContainer = containerPropertyInfo.GetValue(resource) as IODataIdContainer;
601+
if (resourceContainer != null)
602+
{
603+
resourceContainer.ODataIdNavigationPath = navigationPath;
604+
containerPropertyInfo.SetValue(resource, resourceContainer);
605+
}
606+
else
607+
{
608+
containerPropertyInfo.SetValue(resource, container);
609+
}
600610
}
601611
}
602612
}

src/Microsoft.AspNet.OData.Shared/Formatter/Serialization/ODataResourceSerializer.cs

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,13 @@ private void WriteDeltaResource(object graph, ODataWriter writer, ODataSerialize
202202
{
203203
writer.WriteStart(resource);
204204
WriteDeltaComplexProperties(selectExpandNode, resourceContext, writer);
205+
WriteDeltaNavigationProperties(selectExpandNode, resourceContext, writer);
205206
//TODO: Need to add support to write Navigation Links, etc. using Delta Writer
206207
//https://github.com/OData/odata.net/issues/155
207208
//CLEANUP: merge delta logic with regular logic; requires common base between ODataWriter and ODataDeltaWriter
208209
//WriteDynamicComplexProperties(resourceContext, writer);
209210
//WriteNavigationLinks(selectExpandNode.SelectedNavigationProperties, resourceContext, writer);
210-
//WriteExpandedNavigationProperties(selectExpandNode.ExpandedNavigationProperties, resourceContext, writer);
211+
//WriteExpandedNavigationProperties(selectExpandNode, resourceContext, writer);
211212

212213
writer.WriteEnd();
213214
}
@@ -226,6 +227,7 @@ private async Task WriteDeltaResourceAsync(object graph, ODataWriter writer, ODa
226227
{
227228
await writer.WriteStartAsync(resource);
228229
await WriteDeltaComplexPropertiesAsync(selectExpandNode, resourceContext, writer);
230+
await WriteDeltaNavigationPropertiesAsync(selectExpandNode, resourceContext, writer);
229231
//TODO: Need to add support to write Navigation Links, etc. using Delta Writer
230232
//https://github.com/OData/odata.net/issues/155
231233
//CLEANUP: merge delta logic with regular logic; requires common base between ODataWriter and ODataDeltaWriter
@@ -275,6 +277,48 @@ internal void WriteDeltaComplexProperties(SelectExpandNode selectExpandNode,
275277
}
276278
}
277279

280+
internal void WriteDeltaNavigationProperties(SelectExpandNode selectExpandNode, ResourceContext resourceContext, ODataWriter writer)
281+
{
282+
Contract.Assert(resourceContext != null);
283+
Contract.Assert(writer != null);
284+
285+
IEnumerable<KeyValuePair<IEdmNavigationProperty, Type>> navigationProperties = GetNavigationPropertiesToWrite(selectExpandNode, resourceContext);
286+
287+
foreach (KeyValuePair<IEdmNavigationProperty, Type> navigationProperty in navigationProperties)
288+
{
289+
ODataNestedResourceInfo nestedResourceInfo = new ODataNestedResourceInfo
290+
{
291+
IsCollection = navigationProperty.Key.Type.IsCollection(),
292+
Name = navigationProperty.Key.Name
293+
};
294+
295+
writer.WriteStart(nestedResourceInfo);
296+
WriteDeltaComplexAndExpandedNavigationProperty(navigationProperty.Key, null, resourceContext, writer, navigationProperty.Value);
297+
writer.WriteEnd();
298+
}
299+
}
300+
301+
internal async Task WriteDeltaNavigationPropertiesAsync(SelectExpandNode selectExpandNode, ResourceContext resourceContext, ODataWriter writer)
302+
{
303+
Contract.Assert(resourceContext != null);
304+
Contract.Assert(writer != null);
305+
306+
IEnumerable<KeyValuePair<IEdmNavigationProperty, Type>> navigationProperties = GetNavigationPropertiesToWrite(selectExpandNode, resourceContext);
307+
308+
foreach (KeyValuePair<IEdmNavigationProperty, Type> navigationProperty in navigationProperties)
309+
{
310+
ODataNestedResourceInfo nestedResourceInfo = new ODataNestedResourceInfo
311+
{
312+
IsCollection = navigationProperty.Key.Type.IsCollection(),
313+
Name = navigationProperty.Key.Name
314+
};
315+
316+
await writer.WriteStartAsync(nestedResourceInfo);
317+
await WriteDeltaComplexAndExpandedNavigationPropertyAsync(navigationProperty.Key, null, resourceContext, writer, navigationProperty.Value);
318+
await writer.WriteEndAsync();
319+
}
320+
}
321+
278322
private async Task WriteDeltaComplexPropertiesAsync(SelectExpandNode selectExpandNode,
279323
ResourceContext resourceContext, ODataWriter writer)
280324
{
@@ -298,7 +342,7 @@ private async Task WriteDeltaComplexPropertiesAsync(SelectExpandNode selectExpan
298342
}
299343

300344
private void WriteDeltaComplexAndExpandedNavigationProperty(IEdmProperty edmProperty, SelectExpandClause selectExpandClause,
301-
ResourceContext resourceContext, ODataWriter writer)
345+
ResourceContext resourceContext, ODataWriter writer, Type type = null)
302346
{
303347
Contract.Assert(edmProperty != null);
304348
Contract.Assert(resourceContext != null);
@@ -331,6 +375,7 @@ private void WriteDeltaComplexAndExpandedNavigationProperty(IEdmProperty edmProp
331375
{
332376
// create the serializer context for the complex and expanded item.
333377
ODataSerializerContext nestedWriteContext = new ODataSerializerContext(resourceContext, selectExpandClause, edmProperty);
378+
nestedWriteContext.Type = type;
334379

335380
// write object.
336381

@@ -355,7 +400,7 @@ private void WriteDeltaComplexAndExpandedNavigationProperty(IEdmProperty edmProp
355400
}
356401

357402
private async Task WriteDeltaComplexAndExpandedNavigationPropertyAsync(IEdmProperty edmProperty, SelectExpandClause selectExpandClause,
358-
ResourceContext resourceContext, ODataWriter writer)
403+
ResourceContext resourceContext, ODataWriter writer, Type type = null)
359404
{
360405
Contract.Assert(edmProperty != null);
361406
Contract.Assert(resourceContext != null);
@@ -388,6 +433,7 @@ await writer.WriteStartAsync(new ODataResourceSet
388433
{
389434
// create the serializer context for the complex and expanded item.
390435
ODataSerializerContext nestedWriteContext = new ODataSerializerContext(resourceContext, selectExpandClause, edmProperty);
436+
nestedWriteContext.Type = type;
391437

392438
// write object.
393439

@@ -1351,6 +1397,43 @@ private IEnumerable<KeyValuePair<IEdmStructuralProperty, PathSelectItem>> GetPro
13511397
}
13521398
}
13531399

1400+
private IEnumerable<KeyValuePair<IEdmNavigationProperty, Type>> GetNavigationPropertiesToWrite(SelectExpandNode selectExpandNode, ResourceContext resourceContext)
1401+
{
1402+
ISet<IEdmNavigationProperty> navigationProperties = selectExpandNode.SelectedNavigationProperties;
1403+
1404+
if (navigationProperties != null)
1405+
{
1406+
IEnumerable<string> changedProperties = null;
1407+
1408+
if (null != resourceContext.ResourceInstance && resourceContext.ResourceInstance is IDelta deltaObject)
1409+
{
1410+
changedProperties = deltaObject.GetChangedPropertyNames();
1411+
dynamic delta = deltaObject;
1412+
1413+
foreach (IEdmNavigationProperty navigationProperty in navigationProperties)
1414+
{
1415+
Object obj = null;
1416+
if (changedProperties == null || changedProperties.Contains(navigationProperty.Name) && delta.DeltaNestedResources.TryGetValue(navigationProperty.Name, out obj))
1417+
{
1418+
yield return new KeyValuePair<IEdmNavigationProperty, Type>(navigationProperty, obj.GetType());
1419+
}
1420+
}
1421+
}
1422+
else if(null != resourceContext.EdmObject && resourceContext.EdmObject is IDelta changedObject)
1423+
{
1424+
changedProperties = changedObject.GetChangedPropertyNames();
1425+
1426+
foreach (IEdmNavigationProperty navigationProperty in navigationProperties)
1427+
{
1428+
if (changedProperties == null || changedProperties.Contains(navigationProperty.Name))
1429+
{
1430+
yield return new KeyValuePair<IEdmNavigationProperty, Type>(navigationProperty, typeof(IEdmChangedObject));
1431+
}
1432+
}
1433+
}
1434+
}
1435+
}
1436+
13541437
private void WriteExpandedNavigationProperties(SelectExpandNode selectExpandNode, ResourceContext resourceContext, ODataWriter writer)
13551438
{
13561439
Contract.Assert(resourceContext != null);

src/Microsoft.AspNet.OData.Shared/Formatter/Serialization/ODataSerializerContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ internal bool IsUntyped
172172
get
173173
{ if (_isUntyped == null)
174174
{
175-
_isUntyped = typeof(IEdmObject).IsAssignableFrom(Type);
175+
_isUntyped = typeof(IEdmObject).IsAssignableFrom(Type) || typeof(EdmChangedObjectCollection).IsAssignableFrom(Type);
176176
}
177177

178178
return _isUntyped.Value;

src/Microsoft.AspNet.OData.Shared/IDeltaSetItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ public interface IDeltaSetItem
2727
/// <summary>
2828
/// Container to hold ODataId
2929
/// </summary>
30-
ODataIdContainer ODataIdContainer { get; set; }
30+
IODataIdContainer ODataIdContainer { get; set; }
3131
}
3232
}

src/Microsoft.AspNet.OData.Shared/Microsoft.AspNet.OData.Shared.projitems

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,12 @@
8484
<Compile Include="$(MSBuildThisFileDirectory)IDeltaSet.cs" />
8585
<Compile Include="$(MSBuildThisFileDirectory)IDeltaSetItem.cs" />
8686
<Compile Include="$(MSBuildThisFileDirectory)DefaultEdmPatchMethodHandler.cs" />
87-
<Compile Include="$(MSBuildThisFileDirectory)EdmPatchMethodHandler.cs" />
87+
<Compile Include="$(MSBuildThisFileDirectory)EdmODataAPIHandler.cs" />
8888
<Compile Include="$(MSBuildThisFileDirectory)DefaultODataAPIHandler.cs" />
8989
<Compile Include="$(MSBuildThisFileDirectory)ODataEdmAPIHandlerFactory.cs" />
9090
<Compile Include="$(MSBuildThisFileDirectory)ODataAPIHandlerFactory.cs" />
9191
<Compile Include="$(MSBuildThisFileDirectory)IODataAPIHandler.cs" />
92+
<Compile Include="$(MSBuildThisFileDirectory)ODataIdResolver.cs" />
9293
<Compile Include="$(MSBuildThisFileDirectory)PathItem.cs" />
9394
<Compile Include="$(MSBuildThisFileDirectory)NavigationPath.cs" />
9495
<Compile Include="$(MSBuildThisFileDirectory)ODataIdContainer.cs" />

src/Microsoft.AspNet.OData.Shared/NavigationPath.cs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
2-
// Licensed under the MIT License. See License.txt in the project root for license information.
1+
//-----------------------------------------------------------------------------
2+
// <copyright file="NavigationPath.cs" company=".NET Foundation">
3+
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
4+
// See License.txt in the project root for license information.
5+
// </copyright>
6+
//------------------------------------------------------------------------------
37

4-
using System.Collections.Concurrent;
58
using System.Collections.Generic;
69
using System.Collections.ObjectModel;
10+
using System.Diagnostics;
711
using System.Linq;
812
using Microsoft.OData.UriParser;
913

@@ -14,52 +18,41 @@ namespace Microsoft.AspNet.OData
1418
/// </summary>
1519
public class NavigationPath
1620
{
17-
private string navigationPathName;
21+
private string _navigationPathName;
1822
private ReadOnlyCollection<ODataPathSegment> _pathSegments;
19-
private ConcurrentDictionary<string, PathItem[]> _pathItemCache = new ConcurrentDictionary<string, PathItem[]>();
23+
PathItem[] _pathItems;
2024

2125
/// <summary>
22-
/// Constructor which takes and odataId and creates PathItems
23-
/// </summary>
24-
public NavigationPath()
25-
{
26-
27-
}
28-
29-
/// <summary>
30-
/// Constructor which takes and odataId and creates PathItems
26+
/// Initializes a new instance of the <see cref="NavigationPath"/> class.
3127
/// </summary>
3228
/// <param name="navigationPath">ODataId in string format</param>
3329
/// <param name="pathSegments">Pathsegment collection</param>
3430
public NavigationPath(string navigationPath, ReadOnlyCollection<ODataPathSegment> pathSegments)
3531
{
36-
navigationPathName = navigationPath;
32+
Debug.Assert(navigationPath != null);
33+
34+
_navigationPathName = navigationPath;
3735
_pathSegments = pathSegments;
3836
}
3937

4038

4139
/// <summary>
42-
/// NavigationPath/ODataId in string
40+
/// Gets the NavigationPath name
4341
/// </summary>
44-
public string NavigationPathName { get { return navigationPathName; } }
42+
public string NavigationPathName { get { return _navigationPathName; } }
4543

4644
/// <summary>
4745
/// To Get ODataId in Parsed format
4846
/// </summary>
4947
/// <returns>Array of PathItems</returns>
5048
public PathItem[] GetNavigationPathItems()
51-
{
52-
PathItem[] pathItems;
53-
if(!_pathItemCache.TryGetValue(navigationPathName, out pathItems))
49+
{
50+
if(_pathItems == null && _pathSegments != null)
5451
{
55-
if (_pathSegments != null)
56-
{
57-
pathItems = ParseODataId();
58-
_pathItemCache.TryAdd(navigationPathName, pathItems);
59-
}
52+
_pathItems = ParseODataId();
6053
}
6154

62-
return pathItems;
55+
return _pathItems;
6356
}
6457

6558
private PathItem[] ParseODataId()
@@ -69,7 +62,7 @@ private PathItem[] ParseODataId()
6962

7063
foreach (ODataPathSegment segment in _pathSegments)
7164
{
72-
if (segment is EntitySetSegment || segment is NavigationPropertySegment)
65+
if (segment is EntitySetSegment || segment is NavigationPropertySegment || segment is PropertySegment)
7366
{
7467
pathItems.Add(new PathItem());
7568
currentPathItem = pathItems.Last();

0 commit comments

Comments
 (0)