Skip to content

Commit

Permalink
GitHub#107 - NullReferenceException in OData client Graph.Unreachable…
Browse files Browse the repository at this point in the history
…Vertices()
  • Loading branch information
lewischeng-ms committed Apr 2, 2015
1 parent d1f42f9 commit 1701387
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 9 deletions.
14 changes: 10 additions & 4 deletions src/Microsoft.OData.Client/Binding/BindingGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -887,11 +887,17 @@ public void RemoveUnreachableVertices(Action<object> detachAction)
/// </remarks>
private IEnumerable<Vertex> UnreachableVertices()
{
if (this.vertices.Count == 0)
{
// If there is no vertex in the graph, there is no unreachable vertex as well.
return Enumerable.Empty<Vertex>();
}

Queue<Vertex> q = new Queue<Vertex>();

this.Root.Color = VertexColor.Gray;
q.Enqueue(this.Root);

while (q.Count != 0)
{
Vertex current = q.Dequeue();
Expand All @@ -904,10 +910,10 @@ private IEnumerable<Vertex> UnreachableVertices()
q.Enqueue(e.Target);
}
}

current.Color = VertexColor.Black;
}

return this.vertices.Values.Where(v => v.Color == VertexColor.White).ToList();
}
}
Expand Down
84 changes: 79 additions & 5 deletions test/EndToEndTests/Tests/Client/BindingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@

namespace Microsoft.Test.OData.Tests.Client
{
using System.Collections.ObjectModel;
using Microsoft.OData.Client;
using System.Linq;
using System.IO;
using System.Net;
using System;
#if SILVERLIGHT
using Microsoft.Silverlight.Testing;
#endif

using Microsoft.Test.OData.Services.TestServices;
using Microsoft.Test.OData.Services.TestServices.AstoriaDefaultServiceReference;
Expand Down Expand Up @@ -74,6 +70,84 @@ public void LoadPropertyCollection()

this.EnqueueTestComplete();
}

#if !PORTABLELIB && !SILVERLIGHT
[TestMethod]
public void LoadCollectionExceptionShouldNotRuinEntityTracking()
{
var ctxwrap = this.CreateWrappedContext<DefaultContainer>();
var context = ctxwrap.Context;
int[] customerIds = { /*existing*/-9, /*non-existing*/0, /*existing*/-10 };
foreach (var customerId in customerIds)
{
Customer customer = null;

try
{
var query = context.Customer.Where(c => c.CustomerId == customerId);
var collection = new DataServiceCollection<Customer>(query);
customer = collection.Single();
}
catch (DataServiceQueryException e)
{
var inner = e.InnerException as DataServiceClientException;
if (inner != null && inner.StatusCode == (int)HttpStatusCode.NotFound)
{
continue;
}

throw;
}

context.SaveChanges();
}
}

[TestMethod]
public void CanContinueLoadEntityAfterLoadCollectionException()
{
var ctxwrap = this.CreateWrappedContext<DefaultContainer>();
var context = ctxwrap.Context;
DataServiceCollection<Customer> collection = null;
int[] customerIds = { /*non-existing*/0, /*existing*/-10, /*existing*/-9 };
foreach (var customerId in customerIds)
{
Customer customer = null;

try
{
var query = context.Customer.Where(c => c.CustomerId == customerId);

if (collection == null)
{
collection = new DataServiceCollection<Customer>(query);
}
else
{
collection.Load(query);
}

customer = collection.Single();
}
catch (DataServiceQueryException e)
{
var inner = e.InnerException as DataServiceClientException;
if (inner != null && inner.StatusCode == (int)HttpStatusCode.NotFound)
{
continue;
}

throw;
}

// TODO: why DeleteObject won't trigger the callback in the observer to remove the entity in DataServiceCollection.
// context.DeleteObject(customer);

collection.Remove(customer);
context.SaveChanges();
}
}
#endif
#endregion

#region Remove tests
Expand Down

0 comments on commit 1701387

Please sign in to comment.