I have one service method with below syntax -
public async Task<List<responseModel>> SearchAsync(RequestModel request)
{
var temp = await _dbservice.searchAsyncDB(request);
// manipulation with temp
foreach(var i in temp)
{
// manipulation with i
var order = await checkstatus(i.orders); // this is a private method call
}
return order;
}
private async Task<someModel> CheckStatus(int orderNumbers)
{
// manipulation with ordernumber
var model = await checkagain(orderNumber) // private call that has Database Call
}
private async Task<someModel> checkagain(int ordernumber)
{
var temp = await _dbservice.checkagainDB(); // database call
}
Basically Multiple private methods with database call. Not sure if I can mock this using Moq or need to refactor the whole code.
Related
I wrote this code in my Repository
Task<bool> UpdateUserAsync(User user);
But I do not know how to write supplementary code in the implementer class
This code receives the information of a user and edits it in the database
Given that this method must be Async
I'm not entirely sure what you want to do, post your code and you might get a better response but if you're asking about how to write an async method then it's pretty straightforward and clean.
If your "Repository" that you refer to is an interface and you're asking how to write your implementation async then you'll want to do something like this:
public async Task<bool> UpdateUserAsync(User user){
// Check the user exists
var existingUser = await GetUserAsync(user.Id);
if (existingUser == null) {
return false;
}
var success = await DoMySaveTransactions(); // This would be where you commit to your chosen backend.
return success;
}
If you're asking about how to use your new repository then you'd use something like the following inside a method which is decorated with async.
async void UpdateUsername(User existingUser, string newUsername) {
existingUser.username = newUsername;
var success = await _myRepository.UpdateUserAsync(existingUser);
// Do something with success.
}
If you want to use the implementation in a non async method then your code would be something like...
void UpdateUsername(User existingUser, string newUsername) {
existingUser.username = newUsername;
var success = myRepository.UpdateUserAsync(existingUser).GetAwaiter().GetResult();
// Do something with success.
}
If I've misunderstood what you're looking to do, please add some more explanation.
Is your problem in the async part, or in the "fetch and update user" part?
The parts about "Fetch and update user" are difficult to describe if you don't tell us the method you are using to access the database: are you using entity framework? SQL?
SQL, DbConnection, DbCommand
Let's assume you have already synchronous methods:
public User FetchUserById(int userId) {...}
private void UpdateExistingUser(User user) {...}
You will have to create similar async methods:
public Task<User> FetchUserByIdAsync(int userId);
private Task UpdateExistingUserAsync(User user);
If you use SQL, you will probably use class DbCommand and methods ExecuteReader, and ExecuteNonQuery. For your async methods, use similar async methods.
Note: to use DisposeAsync, you need C# 8. Otherwise use try ... finally and call DisposeAsync explicitly
private async dbConnection CreateFetchUserCommand(
DbConnection Connection,
int userId)
{
var dbCommand = connection.CreateCommand();
dbCommand.CommandText = ...
var dbParameter = dbCommand.CreateParameter();
... // etc.
return dbCommand;
}
private async DbCommand CreateUpdateUserCommand(DbConnection connection, User user)
{
var dbCommand = connection.CreateCommand();
dbCommand.CommandText = ...
var dbParameter = dbCommand.CreateParameter();
... // etc.
return dbCommand;
}
public Task<User> FetchUserByIdAsync(int userId)
{
using (var dbConnection = new DbConnection(...))
{
await dbConnection.OpenAsync();
using (var dbCommand = dbConnection.CreateFetchUserCommand(dbConnection, userId))
{
using (var dataReader = await dbCommand.ExecuteReaderAsync())
{
// use async methods to access fetched data
User user = await ...
return user;
}
}
}
}
Similarly: add an UpdateExistingUserAsync which is similar to your existing UpdateUser.
public UpdateUser(User user)
{
// TODO: exception if user null
User existingUser = await FetchUserById(user.Id);
if (existingUser == null)
{
// user does not exist
}
else
{
... // copy values from user to existingUser
await UpdateExistingUserAsync(existingUser);
}
}
The copying from user to existingUser makes it possible to update only the values that you provided. if you always want to update the complete user, then the FetchUserById is not necessary.
Entity Framework
using (var dbConext = new MyDbContext(...))
{
User existingUser = await dbConnection.Users.FindAsync(user.Id)
if (existingUser != null)
{
... // copy values from user to existingUser
await dbContext.SaveAsync();
}
I am trying to use an async task to read from my sqlite db using sqlite.net and my basic class is this one below:
public class Students
{
public string Fullname { get; }
public string Admnumber { get; }
}
A quick example of implementing this library is:
public static IEnumerable<Students> QueryVals ()
{
var db = new SQLiteConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.Query<Students> ("select * from students");
}
but now when I try to use it an async task as below:
public static Task<Students> GetStudentsList ()
{
var db = new SQLiteConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.Query<Students> ("select * from students");
}
I get an error:
Cannot implicitly convert type
'System.Collection.Generic.List' to
'System.Threading.Tasks.Task'
even tyring this doesn't work:
private async void Init()
{
IsBusy = true;
var db = new SQLiteConnection("Data Source=assets\\mydb.db;New=False;Version=3");
var myitems = await db.Query<Students>("select * from students");
IsBusy = false;
}
before I finish it gives the error that my class Students does not have GetAwaiter
You can't just make something asynchronous by changing the return type to Task<T>. Firstly, you need to switch to using the SQLiteAsyncConnection object and the async version of the Query method:
new SQLiteAsyncConnection("...");
...
db.QueryAsync<Students>("select * from students");
// ^^^^^
// Add this
Now you have two options. The first is to await the result, as shown in the answer by mm8. The other, and probably the one I would choose is to just return the task and let the caller await:
public static Task<IEnumerable<Students>> GetStudentsListAsync()
{
var db = new SQLiteAsyncConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.QueryAsync<Students>("select * from students");
}
Note I'm also using the common convention of renaming the method to indicate it is async.
A method that returns a Task<T> is supposed to either be async and await something or return a Task.
You could add the async keyword to your method and await the asynchronous QueryAsync method:
public static async Task<IEnumerable<Students>> GetStudentsListAsync()
{
var db = new SQLiteAsyncConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return await db.QueryAsync<Students>("select * from students");
}
Or return an uncompleted task to be awaited by the caller of the method:
public static Task<IEnumerable<Students>> GetStudentsListAsync()
{
var db = new SQLiteAsyncConnection("Data Source=assets\\mydb.db;New=False;Version=3");
return db.QueryAsync<Students>("select * from students");
}
I am trying to implement a async await in my web application for calling a soap service. I have dependency injection implemented which works fine when i make calls to the database.
When i try calling the webservice i get the response but once it exists the query it's a deadlock. I am not able to figure out what's going wrong. I am new to this async stuff appreciate your inputs on this.
This is the way i am calling the services in a mvc application to invoke the call
public void GetPersonData()
{
var persons = queryProcessor.Process(new GetPersonsWhichNeedApiCalls());
var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
SearchAPI(persons).Wait();
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
}
private async Task SearchAPI(IEnumerable<Person> persons)
{
var tasks = persons.Select(async eachPerson =>
{
var result = await asyncQueryProcessor.ProcessAsync(new PersonSearchCall { Name = eachPerson.Name, Id = eachPerson.Id });
commandProcessor.Process(new CreatePersonSearch()
{
PersonSearch = result
});
});
await Task.WhenAll(tasks);
}
query:
namespace Sample.AsyncQueries
{
public class PersonSearchCall : IQuery<PersonSearch>
{
public string Name { get; set; }
public int Id { get; set; }
}
public class PersonSearchCallHandler : IAsyncQueryHandler<PersonSearchCall, PersonSearch>
{
private readonly IQueryProcessor queryProcessor;
private readonly ICommandProcessor commandProcessor;
public PersonSearchCallHandler(ICommandProcessor commandProcessor,
IQueryProcessor queryProcessor)
{
this.queryProcessor = queryProcessor;
this.commandProcessor = commandProcessor;
}
public async Task<PersonSearch> HandleAsync(PersonSearchCall query)
{
var client = new PersonServiceSoapClient();
var personResponses = await client.PersonSearchAsync(inputs).ConfigureAwait(false);
//Build the person Object
return person;
}
}
}
This simple injector i was able to achieve this using the synchronous way but as i am calling a list of persons and each call is taking around 2sec. i am trying to leverage the use of async and await to make multiple calls from the list.
As StriplingWarrior commented, your problem is that you're blocking on async code. You need to use async all the way:
public async Task GetPersonData()
{
var persons= queryProcessor.Process(new GetPersonsWhichNeedApiCalls());
var watch = System.Diagnostics.Stopwatch.StartNew();
await SearchAPI(persons);
var elapsedMs = watch.ElapsedMilliseconds;
}
I'm trying to get the result of this queries to redis (using stackexchange C# client) in parallel but somehow I'm running in deadlock and not sure where
The method for retrieving the data:
public LiveData Get(string sessionId)
{
return GetAsync(sessionId).Result;
}
private async Task<LiveData> GetAsync(string sessionId)
{
var basketTask = GetBasketAsync(sessionId);
var historyTask = GetHistoryAsync(sessionId);
var capturedDataTask = GetCapturedDataAsync(sessionId);
var basket = await basketTask;
var history = await historyTask;
var capturedData = await capturedDataTask;
return new LiveData
{
Basket = basket.IsNullOrEmpty
? new List<Product>()
: JsonConvert.DeserializeObject<List<Product>>(basket),
History = history.Select(cachedProduct
=> JsonConvert.DeserializeObject<Product>(cachedProduct.Value.ToString())).ToList(),
CapturedData = capturedData.ToDictionary<HashEntry, string, object>(
hash => hash.Name, hash => JsonConvert.DeserializeObject(hash.Value))
};
}
And the methods for fetching the cached data from redis are:
private async Task<RedisValue> GetBasketAsync(string key)
{
key = $"{key}{BasketSuffix}";
var redisDb = RedisConnection.Connection.GetDatabase();
redisDb.KeyExpireAsync(key, _expire);
return await redisDb.StringGetAsync(key);
}
private async Task<HashEntry[]> GetHistoryAsync(string key)
{
key = $"{key}{HistorySuffix}";
var redisDb = RedisConnection.Connection.GetDatabase();
redisDb.KeyExpireAsync(key, _expire);
return await redisDb.HashGetAllAsync(key);
}
private async Task<HashEntry[]> GetCapturedDataAsync(string key)
{
key = $"{key}{CapturedDataSuffix}";
var redisDb = RedisConnection.Connection.GetDatabase();
redisDb.KeyExpireAsync(key, _expire);
return await redisDb.HashGetAllAsync(key);
}
I think it's fine calling the KeyExpireAsync like this, just because it's fine to trigger and forget but not sure if that could be related (I tried even removing it and it's still blocked)
The source of the deadlock is this snippet:
public LiveData Get(string sessionId)
{
return GetAsync(sessionId).Result;
}
Instead, invoke it the proper way "async all the way":
public async Task<LiveData> Get(string sessionId)
{
return await GetAsync(sessionId);
}
Invoking .Result can lead to deadlocking, as can using the .Wait() API. Also, from the looks of it -- the .KeyExpireAsync needs to be awaited.
async Task<RedisValue> GetBasketAsync(string key)
{
key = $"{key}{BasketSuffix}";
var redisDb = RedisConnection.Connection.GetDatabase();
await redisDb.KeyExpireAsync(key, _expire);
return await redisDb.StringGetAsync(key);
}
I understand your thought process on not using the await keyword on the .KeyExpireAsync call but if I were writing this code I would most certainly want to await it like I have demonstrated. It is a code smell to have a fire-and-forget, and can be easily avoided.
I currently use the builder pattern to construct my MVC view models.
var viewModel = builder
.WithCarousel(),
.WithFeaturedItems(3),
.Build()
The problem I am coming up against is when I have to make a service call to an async method. This means that my builder method then has to return Task<HomeViewModelBuilder> instead of HomeViewModelBuilder. This prevents me from chaining the build methods as I have to await them.
Example method
public async Task<HomeViewModelBuilder> WithCarousel()
{
var carouselItems = await _service.GetAsync();
_viewModel.Carousel = carouselItems;
return this;
}
Now I have to use await to call the builder methods.
await builder.WithCarousel();
await builder.WithFeaturedItems(3);
Has anyone used async methods with the builder pattern? If so, is it possible to be able to chain the methods or defer the await to the build method.
I have not actually done this before, but here's an alternative to Sriram's solution.
The idea is to capture the tasks in the builder object instead of the result of the tasks. The Build method then waits for them to complete and returns the constructed object.
public sealed class HomeViewModelBuilder
{
// Example async
private Task<Carousel> _carouselTask = Task.FromResult<Carousel>(null);
public HomeViewModelBuilder WithCarousel()
{
_carouselTask = _service.GetAsync();
return this;
}
// Example sync
private int _featuredItems;
public HomeViewModelBuilder WithFeaturedItems(int featuredItems)
{
_featuredItems = featuredItems;
return this;
}
public async Task<HomeViewModel> BuildAsync()
{
return new HomeViewModel(await _carouselTask, _featuredItems);
}
}
Usage:
var viewModel = await builder
.WithCarousel(),
.WithFeaturedItems(3),
.BuildAsync();
This builder pattern works with any numbers of asynchronous or synchronous methods, for example:
public sealed class HomeViewModelBuilder
{
private Task<Carousel> _carouselTask = Task.FromResult<Carousel>(null);
public HomeViewModelBuilder WithCarousel()
{
_carouselTask = _service.GetAsync();
return this;
}
private Task<int> _featuredItemsTask;
public HomeViewModelBuilder WithFeaturedItems(int featuredItems)
{
_featuredItemsTask = _featuredService.GetAsync(featuredItems);
return this;
}
public async Task<HomeViewModel> BuildAsync()
{
return new HomeViewModel(await _carouselTask, await _featuredItemsTask);
}
}
Usage is still the same.
As I said in comments, you could write Extension method for HomeViewModelBuilder as well as Task<HomeViewModelBuilder> and chain it.
public static class HomeViewModelBuilderExtension
{
public static Task<HomeViewModelBuilder> WithCarousel(this HomeViewModelBuilder antecedent)
{
return WithCarousel(Task.FromResult(antecedent));
}
public static async Task<HomeViewModelBuilder> WithCarousel(this Task<HomeViewModelBuilder> antecedent)
{
var builder = await antecedent;
var carouselItems = await builder.Service.GetAsync();
builder.ViewModel.Carousel = carouselItems;
return builder;
}
public static Task<HomeViewModelBuilder> WithFeaturedItems(this HomeViewModelBuilder antecedent, int number)
{
return WithFeaturedItems(Task.FromResult(antecedent), number);
}
public static async Task<HomeViewModelBuilder> WithFeaturedItems(this Task<HomeViewModelBuilder> antecedent, int number)
{
var builder = await antecedent;
builder.ViewModel.FeaturedItems = number;
return builder;
}
}
We're adding couple of methods for single operation so that you can chain it with HomeViewModelBuilder or Task<HomeViewModelBuilder>. Otherwise you'll not be able to call builder.WithCarousel()
Then use it like
private static void Main()
{
HomeViewModelBuilder builder = new HomeViewModelBuilder();
var task = builder
.WithCarousel()
.WithFeaturedItems(3);
}
With the builder pattern you can create a strategy of building the object. It does not construct the object until the build method is called. If the logic to populate the object is in the build method then you can call all of the async methods together.
See example code for your builder below. Its just a demonstration of the concept so you may want to improve on it.
public class Builder
{
private bool hasCarousel = false;
private int featuredItems = 0;
public Builder WithCarousel()
{
hasCarousel = true;
return this;
}
public Builder WithFeaturedItems(int featured)
{
featuredItems = featured;
return this;
}
public BuiltObject Build()
{
if (hasCarousel)
{
// do carousel related calls
}
if (featuredItems > 0)
{
// do featured items related calls.
}
// build and return the actual object.
}
}
The deal with async, is that it has the ripple effect. It tends to spread through your code to keep it async "async all the way".
If you want to allow for the builder pattern (or any other fluent pattern, like LINQ) while keeping it async you need to have an async overload for each of the possible calls you want to make. Otherwise you can't use them, or will use them wrong (with "sync over async" for example).
async-await is fairly new, but I'm sure over time you will have an async option for almost anything.
The accepted answer was pretty helpful, but I think in some cases (at least in mine) it is more helpful to wait on the builder itself instead of the built objects:
public sealed class HomeViewModelBuilder
{
private List<Task<HomeViewModelBuilder>> taskList= new List<Task<HomeViewModelBuilder>>();
public HomeViewModelBuilder WithCarousel(){
taskList.add(WithCarouselInternal());
return this;
}
private async Task<HomeViewModelBuilder> WithCarouselInternal()
{
var result = await _service.GetAsync();
// do something with the result
return this;
}
public HomeViewModelBuilder WithSomthingElse(){
taskList.add(WithSomethingElseInternal());
return this;
}
(...)
public async Task<HomeViewModel> BuildAsync()
{
await Task.WhenAll(taskList);
// On that point we can now be sure that all builds are finished
return new HomeViewModel(...);
}
}
I hope this is a little more generic, because you just have to keep the taskList up to date and also can call the same build-method more than one time in a simple way (you can't overwrite a previous call to a build method because all will Task will be present in the list and so the build will definitely wait till the Task finishes)