Changing a IQueryable synchronous method to async - c#

I want to convert my code to async but i get error converting types,how can i turn this code to async?
public IQueryable<MyProject.Models.Campaign> Where(System.Linq.Expressions.Expression<Func<MyProject.Models.Campaign, bool>> predicate)
{
try
{
return db.Campaigns.Where(predicate);
}
catch
{
return null;
}
}

i found out how to do that , the problem was i had to change IQueryable to IList.
public async Task<IList<MyProject.Models.Campaign>> WhereAsync(System.Linq.Expressions.Expression<Func<MyProject.Models.Campaign, bool>> predicate)
{
try
{
return await db.Campaigns.Where(predicate).ToListAsync();
}
catch
{
return null;
}
}

Related

Failing to write async recursive iteration function

I'm trying to write a recursion method to retrieve the parent of a object (and that parent etc). This in itself isn't a problem but the calls are async which result in the following error:
The body of '.....Recursive(string)' cannot be an iterator block because 'Task<IEnumerable>' is not an iterator interface type [...]csharp(CS1624)
The code:
private async Task<IEnumerable<string>> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (result?.Length > 0)
{
yield return result;
await Recursive(objectId);
}
}
private async Task<string> GetParent(string objectId)
{
await Task.Run(() => { return $"{objectId}/parent"; });
}
I have also tried IAsyncEnumerable but that resulted in the folllowing error:
'IAsyncEnumerable' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'IAsyncEnumerable' could be found (are you missing a using directive or an assembly reference?) [...]csharp(CS1061)
private async IAsyncEnumerable<string> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (result?.Length > 0)
{
yield return result;
await Recursive(objectId);
}
}
private async Task<string> GetParent(string objectId)
{
await Task.Run(() => { return $"{objectId}/parent"; });
}
I'm going to write a while loop to get this to work. But I'm interested if this is possible at all.
Update 2:
Ok, I think I got it. Thanks guys.
private async IAsyncEnumerable<string> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (result?.Length > 0)
{
yield return result;
await foreach (var r2 in Recursive(objectId))
{
yield return r2;
}
}
}
private async Task<string> GetParent(string objectId)
{
await Task.Run(() => { return $"{objectId}/parent"; });
}
The current code wouldn't compile even if it was synchronous, and the result was IEnumerable<string>. The results of Recursive are never returned. It's not possible to just return an IEnumerable from an iterator either.
This code would work. Whether it does anything useful is another matter :
private IEnumerable<string> Recursive(string objectId)
{
var result = GetParent(objectId);
if (!string.IsNullOrEmpty(result))
{
yield return result;
foreach(var r in Recursive(result))
{
yield return r;
}
}
}
private string GetParent(string objectId)
{
return $"{objectId}/parent";
}
Getting it to work asynchronously only needs changing to IAsyncEnumerable and using await:
private async IAsyncEnumerable<string> Recursive(string objectId)
{
var result = await GetParent(objectId);
if (!string.IsNullOrEmpty(result))
{
yield return result;
await foreach(var r in Recursive(result))
{
yield return r;
}
}
}
private Task<string> GetParent(string objectId)
{
return Task.FromResult($"{objectId}/parent");
}

"Object reference not set to an instance of an object" on predicate

I'm trying to find clients which fields have or contain something. Everything works if I hard code predicate, but when I pass predicate it throws a NullReferenceException.
Repo code:
public IEnumerable<Contractor> Find(Func<Contractor, bool> predicate)
{
var test = db.Contractors.Where(x => x.NIP.Contains("7822574676")).ToList(); //this is correct
try
{
return db.Contractors.Where(predicate).ToList(); // this gives exception
}
catch (Exception ex)
{
return null;
}
}
Service code:
public IEnumerable<ContractorShortDataDTO> FindByNIP(string NIP)
{
try {
return Database.Contractors.Find(x => x.NIP.Contains(NIP)).Select(x =>
new ContractorShortDataDTO()
{
NIP = x.NIP,
CompanyName = x.CompanyName,
ID = x.ID
}).AsEnumerable();
} catch(Exception ex) {
return null;
}
}
What is wrong with that code?
Change the type of the argument in the method from
Func<Contractor, bool> predicate
to
Expression<Func<Contractor, bool>> predicate
See also related question Why would you use Expression<Func<T>> rather than Func<T>?

How can I turn an enumerable into an AsyncEnumerable?

I have some code that uses the async extension methods available in Entity Framework Core:
public async Task<MyResult> DoQuery<T>(IQueryable<T> queryable)
{
var count = await queryable.CountAsync();
var firstItems = await queryable
.Take(5)
.ToArrayAsync();
return new MyResult(count, firstItems);
}
This works great when the IQueryable I give the function comes straight from EF. I also wanted to reuse this code to do some logic on a LINQ-to-objects "query":
var evens = Enumerable.Range(0, 10).Where(i => i % 2 == 0);
var result = DoQuery(evens.AsQueryable());
This fails (which isn't too surprising):
System.InvalidOperationException: The provider for the source IQueryable doesn't implement IAsyncQueryProvider. Only providers that implement IEntityQueryProvider can be used for Entity Framework asynchronous operations.
It looks like a refactor is in order, but I'm curious: is there any way to turn a plain enumerable into a "dummy" AsyncEnumerable or AsyncQueryable that treats CountAsync synchronously?
You need to create an in-memory DbAsyncQueryProvider to process the async query. There is a detailed explanation on how to do that here. Scroll to the part about Testing with async queries. Below is the code copy & pasted from that link:
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
namespace TestingDemo
{
internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider
{
private readonly IQueryProvider _inner;
internal TestDbAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}
public IQueryable CreateQuery(Expression expression)
{
return new TestDbAsyncEnumerable<TEntity>(expression);
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestDbAsyncEnumerable<TElement>(expression);
}
public object Execute(Expression expression)
{
return _inner.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}
public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute(expression));
}
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}
}
internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T>
{
public TestDbAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{ }
public TestDbAsyncEnumerable(Expression expression)
: base(expression)
{ }
public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
IQueryProvider IQueryable.Provider
{
get { return new TestDbAsyncQueryProvider<T>(this); }
}
}
internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;
public TestDbAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}
public void Dispose()
{
_inner.Dispose();
}
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}
public T Current
{
get { return _inner.Current; }
}
object IDbAsyncEnumerator.Current
{
get { return Current; }
}
}
}
This may not have been available when the question was asked. It might not cater for the specific EF situation you are asking for. To directly answer the title of your question: "How can I turn an enumerable into an AsyncEnumerable?" or the one in the body of your question: "turn a plain enumerable into a "dummy" AsyncEnumerable...?"
The System.Linq namespace has native support for ToAsyncEnumerable() which does the job (there are several overloads)
If that was not available for whatever reason, you could implement it yourself like so:
public static async IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IEnumerable<T> input)
{
foreach(var value in input)
{
yield return value;
}
}

Issue creating generic wrapper for async library

I have a class Library https://github.com/trydis/FIFA-Ultimate-Team-2014-Toolkit I want to make a wrapper for, instead of just calling FutClient I want to make a FutClientWrapper where I can handle exceptions, reloggin and loggin the interface I want to wrap is https://github.com/trydis/FIFA-Ultimate-Team-2014-Toolkit/blob/master/UltimateTeam.Toolkit/IFutClient.cs
So I made http://pastebin.com/0EJdCbbr
Code snippet
public async Task<AuctionResponse> SearchAsync(SearchParameters searchParameters)
{
return await Invoke(f => f.SearchAsync(searchParameters), searchParameters);
}
public async Task<AuctionResponse> PlaceBidAsync(AuctionInfo auctionInfo, uint bidAmount = 0)
{
return await Invoke(f => f.PlaceBidAsync(auctionInfo, bidAmount), auctionInfo);
}
public async Task<Item> GetItemAsync(long resourceId)
{
return await Invoke(f => f.GetItemAsync(resourceId), resourceId);
}
public TResult Invoke<TResult>(Func<FutClient, TResult> func, object requestDetails = null,
[CallerMemberName] string exceptionMessage = null)
{
try
{
if (LastException + new TimeSpan(0, 0, 30) < DateTime.Now)
{
TResult result = func(_futClient);
return result;
}
}
catch (Exception e)
{
Here I try to wrap and catch any exception thrown inside the Futclient, but instead I get a null exception in for example this line
return await Invoke(f => f.GetItemAsync(resourceId), resourceId);
And it seems its because my
TResult result = func(_futClient);
return result;
Is not run async and it just returns an empty response (All null values)
So I changed it to look like http://pastebin.com/pJkPr2xN
Code snippet:
public async Task<AuctionResponse> GetTradePileAsync()
{
return await NewInvoke<AuctionResponse>(new Task<object>(() => _futClient.GetTradePileAsync()));
}
public async Task<WatchlistResponse> GetWatchlistAsync()
{
return await NewInvoke<WatchlistResponse>(new Task<object>(() => _futClient.GetWatchlistAsync()));
}
public async Task<TResult> NewInvoke<TResult>(Task<object> taskToRun) where TResult : class
{
try
{
taskToRun.Start();
Task.WaitAll(taskToRun);
return taskToRun.Result as TResult;
}
catch (AggregateException ex)
{
//ex.InnerException
return null;
}
catch (Exception e)
{
return null;
}
}
But also here I get exceptions outside my invoke method
So how should I make this so it handles both Task and Task as a response type and takes x number of arguments
And it should then throw any exceptions inside the Invoke method so I only have one place where exceptions needs to be caught
You must await inside the try block before you return, otherwise the exception will not be cought by the catch. Your first attempt was actually closer to the correct way to do it.
public async Task<TResult> Invoke<TResult>(Func<FutClient, Task<TResult>> func, object requestDetails = null,
[CallerMemberName] string exceptionMessage = null)
{
try
{
if (LastException + new TimeSpan(0, 0, 30) < DateTime.Now)
{
TResult result = await func(_futClient).ConfigureAwait(false); //Here we both await for the result and set `ConfigureAwait` to false so we don't need to waist extra time trying to marshal back on to the original Synchronization context as we have no need for it for the rest of the method.
return result;
}
}
catch (Exception e)
{
//...
You then just use it like the following
public Task<AuctionResponse> PlaceBidAsync(AuctionInfo auctionInfo, uint bidAmount = 0)
{
return Invoke(f => f.PlaceBidAsync(auctionInfo, bidAmount), auctionInfo);
}
There is no need to await in this outer function, you can just directly return the Task returned by Invoke

Generically encapsulate action/function with class?

I would like to provide encapsulation of actions/methods generically. I think this should be possible in C# but I'm not able to produce it so it compiles...
The following briefly demonstrates what I want. Is this possible somehow, perhaps by generalizing the class?
Required is:
I want to execute the function/action (see method type) and 'do something' when an error occurs
I want to return the value of the function if the method is a function (otherwise return void if possible)
I want to 'do something' if the return type of the function is a boolean and the value is false.
public class Encapsulator {
private Action _action;
private Func<T> _function;
private MethodType _type; //Action || Function
public Encapsulator(Action action) {
this._action = action;
this._type = MethodType.Action;
}
public Encapsulator(Func<T> func) { //This is not accepted
this._function = func;
this._type = MethodType.Function;
}
public void Execute() {
try {
this._action();
}
catch(Exception ex) {
//do something
throw;
}
}
public T Execute<T>() {
try {
var r = this._function();
if(typeof(r) == bool) {
if(!r)
//do something
}
return r;
} catch(Exception ex) {
//do something
throw;
}
}
}
Your second constructor won't compile because their are no generics applied to the type at the higher level:
public Encapsulator<T>
{
public Encapsulator(Func<T> func)
{
this._function = func;
this._type = MethodType.Function;
}
}
Instead of just introducing new things within the parameters of a method, essentially, we need to specify that those things are 'available' for utilisation in the definitions. So, for instance, if you were trying to add a specific generic method, you could apply it as you have done, but would instead need to do (something which you demonstrate with the Execute method):
public void MyGenericMethod<T>(Func<T> func)
{
}
Noting the first T, we're specifying the existence of T, as such.
There are possibly more issues at hand with your code here, but I believe, on first glance, this to be the crux of the problems you're having.
As for returning variable types, the best you might hope for is returning a plain old object. Or, making use of the dynamic type, however, I wouldn't have thought this would be the way to go and wouldn't recommend it; you can't flip return type from an actual type to a void, though.
New Approach: The action Encapsulator will now return a dummy result (always true).
public class Encapsulator
{
public static Encapsulator<bool> CreateEncapsulator(Action action)
{
return new Encapsulator<bool>(() =>
{
action();
return true;
});
}
public static Encapsulator<T> CreateEncapsulator<T>(Func<T> func)
{
return new Encapsulator<T>(func);
}
}
public class Encapsulator<T>
{
private Func<T> _function;
internal Encapsulator(Func<T> func)
{
this._function = func;
}
public T Execute()
{
try
{
object res = this._function();
Nullable<bool> bres = res as Nullable<bool>;
if (bres.HasValue)
{
if (!bres.Value)
Console.WriteLine("NOT TRUE!");
//do something
}
return (T)res;
}
catch (Exception ex)
{
//do something
throw;
}
}
}
Calling the code:
var withDummyReturn = Encapsulator.CreateEncapsulator(() => Console.WriteLine("Great"));
withDummyReturn.Execute();
var withReturn = Encapsulator.CreateEncapsulator<bool>(() => true);
bool res = withReturn.Execute();

Categories

Resources