Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/Microsoft.OData.Client/DataServiceActionQuerySingleOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,12 @@ public Task<T> GetValueAsync()
/// <summary>Asynchronously sends the request so that this call does not block processing while waiting for the results from the service.</summary>
/// <returns>A task represents the result of the operation. </returns>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
public Task<T> GetValueAsync(CancellationToken cancellationToken)
public async Task<T> GetValueAsync(CancellationToken cancellationToken)
{
return this.context.FromAsync(this.BeginGetValue, this.EndGetValue, cancellationToken);
IEnumerable<T> result = await context.ExecuteAsync<T>(this.RequestUri, XmlConstants.HttpMethodPost, true, cancellationToken, parameters)
.ConfigureAwait(false);

return ClientTypeUtil.CanAssignNull(typeof(T)) ? result.SingleOrDefault() : result.Single();
}

/// <summary>Called to complete the <see cref="Microsoft.OData.Client.DataServiceActionQuery{T}.BeginExecute(AsyncCallback,Object)" />.</summary>
Expand Down
146 changes: 88 additions & 58 deletions src/Microsoft.OData.Client/DataServiceContext.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ public async Task SaveChangesAsyncCancellationTokenTest()

Task response() => _context.SaveChangesAsync(source.Token);
source.Cancel();
var exception = await Assert.ThrowsAsync<OperationCanceledException>(response);
Assert.Equal("The operation was canceled.", exception.Message);
var exception = await Assert.ThrowsAsync<TaskCanceledException>(response);
Assert.Equal("A task was canceled.", exception.Message);
Comment on lines +79 to +80

// SaveChangesAsync with SaveChangesOptions
var c2 = new Customer { CustomerId = 22, Name = "customerTwo" };
Expand All @@ -87,8 +87,8 @@ public async Task SaveChangesAsyncCancellationTokenTest()

Task response2() => _context.SaveChangesAsync(SaveChangesOptions.BatchWithIndependentOperations, source.Token);
source.Cancel();
var exception2 = await Assert.ThrowsAsync<OperationCanceledException>(response2);
Assert.Equal("The operation was canceled.", exception2.Message);
var exception2 = await Assert.ThrowsAsync<TaskCanceledException>(response2);
Assert.Equal("A task was canceled.", exception2.Message);
}

#endregion
Expand Down Expand Up @@ -208,8 +208,8 @@ public async Task LoadPropertyAsyncCancellationTokenTest()

Task response() => _context.LoadPropertyAsync(c1, "Orders", source.Token);
source.Cancel();
var exception = await Assert.ThrowsAsync<OperationCanceledException>(response);
Assert.Equal("The operation was canceled.", exception.Message);
var exception = await Assert.ThrowsAsync<TaskCanceledException>(response);
Assert.Equal("A task was canceled.", exception.Message);

//Get Entity by DataServiceQuery.ExecuteAsync
var query = _context.Customers.Expand(c => c.Orders).Where(c => c.CustomerId == 11) as DataServiceQuery<Customer>;
Expand All @@ -222,13 +222,13 @@ public async Task LoadPropertyAsyncCancellationTokenTest()
var continuation = resp.GetContinuation(customer.Orders);
Task response2() => _context.LoadPropertyAsync(customer, "Orders", continuation, source.Token);
source.Cancel();
var exception2 = await Assert.ThrowsAsync<OperationCanceledException>(response2);
Assert.Equal("The operation was canceled.", exception2.Message);
var exception2 = await Assert.ThrowsAsync<TaskCanceledException>(response2);
Assert.Equal("A task was canceled.", exception2.Message);

Task response3() => _context.LoadPropertyAsync(customer, "Orders", continuation.NextLinkUri, source.Token);
source.Cancel();
var exception3 = await Assert.ThrowsAsync<OperationCanceledException>(response3);
Assert.Equal("The operation was canceled.", exception3.Message);
var exception3 = await Assert.ThrowsAsync<TaskCanceledException>(response3);
Assert.Equal("A task was canceled.", exception3.Message);
}

#endregion
Expand Down Expand Up @@ -291,8 +291,8 @@ Task response() => _context.ExecuteBatchAsync(
});

source.Cancel();
var exception = await Assert.ThrowsAnyAsync<OperationCanceledException>(response);
Assert.Equal("The operation was canceled.", exception.Message);
var exception = await Assert.ThrowsAsync<TaskCanceledException>(response);
Assert.Equal("A task was canceled.", exception.Message);
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,12 @@ public override IODataResponseMessage GetResponse()
});
}

public override Task<IODataResponseMessage> GetResponseAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(GetResponse());
}

public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
{
return GetCompletedTask(callback, state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,12 @@ public override IODataResponseMessage GetResponse()
});
}

public override Task<IODataResponseMessage> GetResponseAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(GetResponse());
}

public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
{
return GetCompletedTask(callback, state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,18 +308,13 @@ public void EndGetValue_ThrowsInvalidOperationException_WhenMultipleResults()
}

[Fact]
public async Task GetValueAsync_UsesBeginEndPattern_ReturnsSingleValue()
public async Task GetValueAsync_UsesNativeAsyncPath_ReturnsSingleValue()
{
// Arrange
var asyncResult = new TestAsyncResult();
var context = new TestDataServiceContext<int>(new Uri("http://service/"))
{
BeginExecuteFunc = (uri, callback, state, method, single, parameters) =>
{
callback?.Invoke(asyncResult);
return asyncResult;
},
EndExecuteFunc = (ar) => new[] { 567 }
ExecuteAsyncFunc = (uri, method, single, cancellationToken, parameters) =>
Task.FromResult<IEnumerable<int>>(new[] { 567 })
};

var query = new DataServiceActionQuerySingle<int>(
Expand All @@ -334,18 +329,13 @@ public async Task GetValueAsync_UsesBeginEndPattern_ReturnsSingleValue()
}

[Fact]
public async Task GetValueAsync_UsesBeginEndPattern_ThrowsInvalidOperationException_WhenNoResultsForNonNullableType()
public async Task GetValueAsync_UsesNativeAsyncPath_ThrowsInvalidOperationException_WhenNoResultsForNonNullableType()
{
// Arrange
var asyncResult = new TestAsyncResult();
var context = new TestDataServiceContext<int>(new Uri("http://service/"))
{
BeginExecuteFunc = (uri, callback, state, method, single, parameters) =>
{
callback?.Invoke(asyncResult);
return asyncResult;
},
EndExecuteFunc = (ar) => Enumerable.Empty<int>()
ExecuteAsyncFunc = (uri, method, single, cancellationToken, parameters) =>
Task.FromResult(Enumerable.Empty<int>())
};

var query = new DataServiceActionQuerySingle<int>(
Expand All @@ -357,18 +347,13 @@ public async Task GetValueAsync_UsesBeginEndPattern_ThrowsInvalidOperationExcept
}

[Fact]
public async Task GetValueAsync_UsesBeginEndPattern_Throws_WhenMultipleResults()
public async Task GetValueAsync_UsesNativeAsyncPath_Throws_WhenMultipleResults()
{
// Arrange
var asyncResult = new TestAsyncResult();
var context = new TestDataServiceContext<int>(new Uri("http://service/"))
{
BeginExecuteFunc = (uri, callback, state, method, single, parameters) =>
{
callback?.Invoke(asyncResult);
return asyncResult;
},
EndExecuteFunc = (ar) => new[] { 1, 2 }
ExecuteAsyncFunc = (uri, method, single, cancellationToken, parameters) =>
Task.FromResult<IEnumerable<int>>(new[] { 1, 2 })
};

var query = new DataServiceActionQuerySingle<int>(
Expand All @@ -379,24 +364,41 @@ public async Task GetValueAsync_UsesBeginEndPattern_Throws_WhenMultipleResults()
await Assert.ThrowsAsync<InvalidOperationException>(() => query.GetValueAsync());
}

[Fact]
public async Task GetValueAsync_UsesNativeAsyncPath_ReturnsNullForNullableType()
{
// Arrange
var context = new TestDataServiceContext<int?>(new Uri("http://service/"))
{
ExecuteAsyncFunc = (uri, method, single, cancellationToken, parameters) =>
Task.FromResult(Enumerable.Empty<int?>())
};
var query = new DataServiceActionQuerySingle<int?>(context, "http://service/Action");

// Act
int? result = await query.GetValueAsync();

// Assert
Assert.Null(result);
}

[Fact]
public async Task GetValueAsync_WithCancellationToken_ReturnsExpectedResult()
{
// Arrange
var asyncResult = new TestAsyncResult();
using var cancellationTokenSource = new CancellationTokenSource();
var context = new TestDataServiceContext<int>(new Uri("http://service/"))
{
BeginExecuteFunc = (uri, callback, state, method, single, parameters) =>
ExecuteAsyncFunc = (uri, method, single, cancellationToken, parameters) =>
{
callback?.Invoke(asyncResult);
return asyncResult;
},
EndExecuteFunc = (ar) => new[] { 888 }
Assert.Equal(cancellationTokenSource.Token, cancellationToken);
return Task.FromResult<IEnumerable<int>>(new[] { 888 });
}
};
var query = new DataServiceActionQuerySingle<int>(context, "http://service/Action");

// Act
var result = await query.GetValueAsync(CancellationToken.None);
var result = await query.GetValueAsync(cancellationTokenSource.Token);

// Assert
Assert.Equal(888, result);
Expand Down Expand Up @@ -480,6 +482,7 @@ public void EndGetValue_ThrowsIfAsyncResultIsNull()
private class TestDataServiceContext<T> : DataServiceContext
{
public Func<Uri, string, bool, BodyOperationParameter[], IEnumerable<T>> ExecuteFunc { get; set; }
public Func<Uri, string, bool, CancellationToken, BodyOperationParameter[], Task<IEnumerable<T>>> ExecuteAsyncFunc { get; set; }
public Func<Uri, AsyncCallback, object, string, bool, BodyOperationParameter[], IAsyncResult> BeginExecuteFunc { get; set; }
public Func<IAsyncResult, IEnumerable<T>> EndExecuteFunc { get; set; }

Expand All @@ -501,6 +504,23 @@ public override IAsyncResult BeginExecute<TElement>(Uri requestUri, AsyncCallbac
throw new NotImplementedException();
}

public override async Task<IEnumerable<TElement>> ExecuteAsync<TElement>(Uri requestUri, string httpMethod, bool singleResult, CancellationToken cancellationToken, params OperationParameter[] operationParameters)
{
if (typeof(TElement) == typeof(T) && ExecuteAsyncFunc != null)
{
IEnumerable<T> result = await ExecuteAsyncFunc(
requestUri,
httpMethod,
singleResult,
cancellationToken,
operationParameters.Cast<BodyOperationParameter>().ToArray());

return (IEnumerable<TElement>)result;
}

throw new NotImplementedException();
}

public override IEnumerable<TElement> EndExecute<TElement>(IAsyncResult asyncResult)
{
if (typeof(TElement) == typeof(T) && EndExecuteFunc != null)
Expand Down
Loading