I am using .net core 6.0. I am getting this error when I am calling same method from different places. I tried calling this method GetEmployeeByEmployeeNumber from inside Index and I dont get any error and the method returns the object employee with value values populated in employee
public async Task<IActionResult> Index()
{
EmployeeInfo employee = await _employeeService.GetEmployeeByEmployeeNumber(up.EmployeeId);
PopulatePDFDoc();
return View();
}
public async Task<EmployeeInfo?> GetEmployeeByEmployeeNumber(string employeeId)
{
List<int> emplyoeeInfoId = new List<int>();
UserPrincipal up = utilities.UserADIdentity.GetADUserInfo(WindowsIdentity.GetCurrent().Name.ToString());
emplyoeeInfoId = _ackContext.EmployeeInfos.Where(e => e.EmployeeNumber == employeeId).OrderBy(e => e.DateFormFilled).Select(e => e.EmployeeInfoId).ToList();
var employee = await _ackContext.EmployeeInfos.Include(e => e.EmergencyInfos.Where(p => p.EmployeeInfoId.Equals(emplyoeeInfoId.LastOrDefault()))).Where(e=>e.EmployeeInfoId.Equals(emplyoeeInfoId.LastOrDefault())).FirstOrDefaultAsync();
return employee;
}
If I call the same method GetEmployeeByEmployeeNumber from inside PopulatePDFDoc(); then I get an error saying System.InvalidOperationException: 'Invalid operation. The connection is closed.'
below is my PopulatePDFDoc
public async void PopulatePDFDoc()
{
AckPackage.Data.PDFPopulate.DocPDF doc = new Data.PDFPopulate.DocPDF();
EmployeeInfo employee = await _employeeService.GetEmployeeByEmployeeNumber(up.EmployeeId);
}
below is the screen shot of the error:
I am new to .net core. Any help on this will be highly appreciated.
You need to await the call to PopulatePDFDoc() inside the Index method.
Like this:
await PopulatePDFDoc();
Always use await when calling an async method!
The reason you’re getting a “connection closed” error, is because the call to PopulatePDFDoc() is not being “awaited”, and the server request ends before the asynchronous method can run.
Also, PopulatePDFDoc() should return Task instead of void, like this:
public async Task PopulatePDFDoc()
Another thing I noticed that may cause you issues is your _ackContext which looks like it's a class-wide member variable based on the snippet you shared, meaning that same context-instance is shared between multiple methods.
However the context itself is actually not "thread safe", as can be read in Microsofts documentation here: https://learn.microsoft.com/en-us/ef/ef6/fundamentals/working-with-dbcontext which means that if multiple async methods use the same context - which they do in your example - you may run into issues.
The recommended approach is to create the context when you need it, and use the using syntax to make sure it's disposed properly after your work is finished. Like this:
using (var ackContext = new EmployeeContext())
{
// Perform data access using the context here
}
Try using that in your GetEmployeeByEmployeeNumber method and see if it helps as well :)
Related
I am using a client to interact with CloudMQTT API. I am trying to create a user but after trying the code provided below, I was not able to create a user. When using the code provided within the Github repository for this project, I noticed that I am unable to make use of a ShouldThrow() method (apparently it should be provided by Fluent Assertions).
I did find a post on StackOverflow which looked very similar to the problem I am having. In the question is mentioned that FluentAssertions does not support async methods. In the example code for the client, however, I can see that the ShouldThrow() method is used regardless of this fact.
How could I get the ShoudldThrow() to work or do I even need it to work (because I think it is only supposed to be required in this code if you are applying unit testing)?
This is what a tried so far:
public static async void CreateCloudUser(ICloudMqttApi client)
{
var users = await client.GetUsers();
Console.WriteLine($"Creating a user. Current users available: {users.Count}");
var expectedUser = new NewUser
{
Password = $"{Guid.NewGuid()}",
Username = $"staging-{Guid.NewGuid()}",
};
var createUserResponse = await client.CreateUser(expectedUser);
createUserResponse.IsSuccessStatusCode.Should().BeTrue();
var actual = await client.GetUser(expectedUser.Username);
actual.Should().NotBeNull();
actual.Username.Should().Be(expectedUser.Username);
//users.Should().Contain(u => u.Username == expectedUser.Username); // <-- This throws an exception as well, but not of importance for this specific question.
Func<Task> verifyUser = async () => await client.GetUser(expectedUser.Username);
verifyUser.ShouldThrow<ApiException>() // <-- Not recognized
.And.StatusCode.Should().Be(HttpStatusCode.NotFound);
Console.WriteLine($"Created a user. Current users available: {users.Count}");
}
The client is defined in the way as provided in the documentation for the client right before calling the method:
var client = CloudMqttApi.GetInstance("username", "password");
The user count will result in the same number before and after executing the method (which obviously should have incremented).
Given the asynchronous nature of the shown code, the syntax should be
//...
var deleteResponse = await client.DeleteUser(expectedUser.Username);
deleteResponse.IsSuccessStatusCode.Should().BeTrue();
Func<Task> verifyUser = async () => await client.GetUser(expectedUser.Username);
var exceptionAssertion = await verifyUser.Should().ThrowAsync<ApiException>();
exceptionAssertion.And.StatusCode.Should().Be(HttpStatusCode.NotFound);
//...
Reference FluentAssertions: Exceptions
Also avoid using async void. Have the function return Task
public static async Task CreateCloudUser(ICloudMqttApi client) {
//...
}
Reference Async/Await - Best Practices in Asynchronous Programming
Imagine this is a method performing a DB query and returning a result, which in case of null is replaced with a default value (Null object pattern).
public ResultObj Get()
{
var result = dbContext.GetSomeResult();
return result ?? ResultObj.NullValue;
}
Imagine this DB query is a long-running process, so I would use async/await to execute this process in a separate thread. Suppose that the dbContext.GetSomeResultAsync() method is available.
How can be this method converted in an asynchronous one so that I can write something like this?
var resultTask = GetAsync();
var otherResultTask = GetSomethingElseAsync();
Task.WaitAll(resultTask, otherResultTask);
var myResult = resultTask.Result;
var myOtherResult = otherResultTask.Result;
I tried this solution.
public async Task<ResultObj> GetAsync()
{
var result = await dbContext.GetSomeResultAsync();
return result ?? ResultObj.NullValue;
}
First, I'm wondering why this code compiles: why can I return ResultObj when Task<ResultObj> is expected?
Second, this code predictably results in a deadlock, as clearly explained by the great number of resources about async deadlocks anti-patterns. The deadlock can be prevented by using .ConfigureAwait(false) method after the async call. Is this the right way to go? Are there any hidden drawbacks in this case? Is it a general rule?
I also tried this.
public async Task<ResultObj> GetAsync()
{
return await Task.Run(() => {
var result = dbContext.GetSomeResult();
return result ?? ResultObj.NullValue;
});
}
This results in a deadlock, too. This time I cannot even figure out why.
Edit: possible solution
Finally, after having read this, I found a solution to my problem.
My generic query wrapper method is like this.
public async Task<ResultObj> GetAsync()
{
var result = await dbContext.GetSomeResultAsync();
return result ?? ResultObj.NullValue;
}
On calling method, I use this pattern.
public async Task<CollectedResults> CollectAsync()
{
var resultTask = GetAsync();
var otherResultTask = GetSomethingElseAsync();
//here both queries are being executed.
//...in the while, optionally, here some other synchronous actions
//then, await results
var result = await resultTask;
var otherResult = await otherResultTask;
//here process collected results and return
return new CollectedResults(...);
}
It is worth mentioning that the above code, wrapped in a domain class, is called by a Controller action. In order for this to work I had to make async the methods all the way up, until Controller action, which now appears as follows.
public async Task<CollectedResults> Get()
{
return await resultsCollector.CollectAsync();
}
This way, deadlock doesn't happen anymore and execution time greatly improves with respect to the synchronous version.
I don't know if this is the canonical way of executing parallel queries. But it works and I don't see particular pitfalls in the code.
First of all, regarding :
so I would use async/await to execute this process in a separate thread.
There is no new thread created when we use async and await
Secondly:
why can I return ResultObj when Task is expected?
the Task<TResult> as return type of method tells that it returns a Task of type TResult but we need to return object of type that TResult back from it so the method can be awaited and when using Task<TResult> as reutrn type we should be using async and await to do the work.
Lastly:
this code predictably results in a deadlock
You are using async keyword with method signatures and also await the next async method call being done from within the method. So apparently it looks like the code in first example you have posted shouldn't be deadlocked, if the method GetSomeResultAsync you are consuming is really a async method and is properly implemented.
I suggest to study more about the async await before getting in to it, following is a good article to start with:
https://blog.stephencleary.com/2012/02/async-and-await.html
In my service layer I wanted to fire multiple methods asynchronously and await for their results.
I tried with one at a time and it is erroring out.
In my service class I called the method like
var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = await _validChapterCodesTask;
And in DAL class the method definition looks like
public async Task<IEnumerable<ChapterCodeValidationOutput>> validateChapterCodeDetails(GroupMembershipValidationInput gmvi)
{
Repository rep = new Repository();
if (!gmvi._chapterCodes.All(x => x.Equals("")))
{
var _validChapterCodes = await rep.ExecuteStoredProcedureAsync<Entities.Upload.ChapterCodeValidationOutput>(SQL.Upload.UploadValidation.getChapterCodeValidationSQL(gmvi._chapterCodes),null);
return _validChapterCodes;
}
else
return new List<ChapterCodeValidationOutput>();
}
Error message
Error 208 The await operator can only be used within an async method. Consider marking this method with the async modifier and changing its return type to Task<ARC.Donor.Business.Upload.GroupMembershipValidationOutput>. C:\Users\m1034699\Desktop\Stuart_Upgrade_2.1_New Approach\Stuart_Export_Upload_v2.1\Stuart Web Service\ARC.Donor.Service\Upload\UploadValidationServices.cs 34 13 ARC.Donor.Service
in lines
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = await _validChapterCodesTask;
What am I doing wrong ?
The error message is very explicit. It is telling you that you're Service class method is incorrectly attempting to use the async keyword. In order to fix this, you should be using "Async all the way" as defined in Stephen Cleary's post on MSDN as a best practice.
For example, if you're service class has a method body that is working with Task or Task<T>, or attempting to use the await keyword the method signature for this corresponding method body must be async (as the async keyword enables a method to use the await keyword). Additionally this method itself should also be Task or Task<T> returning, with very few exceptions to that rule.
Personally, I would alter your DAL class to simply return the operation that represents the asynchronous work without actually awaiting it. If you think about it, the body of the validateChapterCodeDetails method does not actually need to do anything with the results, it just needs to return them (instead of materializing them there). Consider the following:
public Task<IEnumerable<ChapterCodeValidationOutput>>
validateChapterCodeDetails(GroupMembershipValidationInput gmvi)
{
var rep = new Repository();
return gmvi._chapterCodes.All(x => x.Equals(""))
? new List<ChapterCodeValidationOutput>()
: rep.ExecuteStoredProcedureAsync
<Entities.Upload.ChapterCodeValidationOutput>
(SQL.Upload.UploadValidation
.getChapterCodeValidationSQL(gmvi._chapterCodes),null)
}
Since your Task<IEnumerable<ChapterCodeValidationOutput>> variable has already been awaited, you can access the .Result property to get what you're looking for.
Then in your Service class your method would look like this:
public async Task ConsumeAsync()
{
var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = _validChapterCodesTask.Result;
// Do something with it...
}
Here is a .NET fiddle that should help to exemplify this for you better.
NOTE
I would also caution using IEnumerable as it pertains to your repo, you should ensure that the results from the Database are not occurring via deferred execution, otherwise you risk the potential for connection issues, i.e.; unintentionally leaving a connection open, or not properly closing one.
In the Service class where you call
var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);
await Task.WhenAll(_validChapterCodesTask);
var _chapterCodeResult = await _validChapterCodesTask;
add a async to the method signature where await Task.WhenAll(_validChapterCodesTask); is called. And when this method also has a return type you have to wrap this type in a Task like the exception shows:
Task<ARC.Donor.Business.Upload.GroupMembershipValidationOutput>
E.g. if you have the following method:
public GroupMemberShipValidationOutput validate(..) {
...
await Task.WhenAll(_validChapterCodesTask);
...
}
You have to change the method signature to:
public async Task<GroupMemberShipValidationOutput> validate(..) {
...
await Task.WhenAll(_validChapterCodesTask);
...
}
I have an online database from Parse.com. There's a table "Vakantie", that contains 3 objects, so the table data isn't big.
I'm trying to get all the objects from that table so I can display them through my VakantieController in a View.
Parse has an own documentation where sample code is provided. I copied their sample code and edited it so that it fits for my website.
The сode:
VakantieController:
public ActionResult Index()
{
var vakantiesTask = vakantieRepository.FindAll();
IEnumerable<Vakantie> vakanties = vakantiesTask.Result;
return View(vakanties);
}
VakantieRepository (class that contains code to retrieve from en write to the database):
public async Task<IList<Vakantie>> FindAll()
{
var query = from v in ParseObject.GetQuery("Vakantie")
orderby v.Get<string>("titel") ascending
select v;
IEnumerable<ParseObject> objects = await query.FindAsync();
IList<Vakantie> vakanties = new Vakantie[] { };
foreach (ParseObject vakantieObject in objects)
{
Vakantie vakantie = GetVakantie(vakantieObject);
vakanties.Add(vakantie);
}
return vakanties;
}
The method `GetVakantie(vakantieObject() is a method I wrote that converts the ParseObject I get from the query result to a Vakantie object from my domain.
When I run this code, I get until the line:
IEnumerable<ParseObject> objects = await query.FindAsync();
and when Visual Studio actually performs this command, my website just keeps loading and loading. I never get over this line to the next one. It is stuck right there.
Does anyone has a solution for this?
You're running into a classic deadlock scenario that I describe in full on my blog and an MSDN article. In summary, await will capture the current "context" and use that to resume the async method. Furthermore, the ASP.NET context will only allow one thread at a time. So when a request thread is blocked (on Task<T>.Result), the await inside of FindAll cannot resume the async method on that context, and you end up with a deadlock.
To correct it, use async "all the way"; i.e., don't use Task<T>.Result:
public async Task<ActionResult> Index()
{
var vakantiesTask = vakantieRepository.FindAll();
IEnumerable vakanties = await vakantiesTask;
return View(vakanties);
}
I'm working with Identity 2.0 in MVC5, and I'm trying to get the first role for the current user.
This bit of code doesn't report any errors:
var DatabaseContext = new ApplicationDbContext();
var thisUserAccount = DatabaseContext.Users.FirstAsync(u => u.Id == Id);
This bit of code:
var DatabaseContext = new ApplicationDbContext();
var thisUserAccount = await DatabaseContext.Users.FirstAsync(u => u.Id == Id);
reports the following error:
The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'
The method is an asynchronous method, so why cant I use "await"?
Also, will calling:
DatabaseContext.Users.Load();
before the FirstAsync optimise things a bit (rather than building a ToList which I'm assuming FirstSync does)?
I'm still trying to get to grips with what the async stuff can do, so any useful links will be much appreciated.
You need to mark the method that's using await as being async:
async Task<UserAccount> DoStuff()
{
var DatabaseContext = new ApplicationDbContext();
var thisUserAccount = await DatabaseContext.Users.FirstAsync(u => u.Id == Id);
return thisUserAccount;
}
That's what the error message is telling you.
The following characteristics summarize what makes a method async (your missing the first).
The method signature includes an async modifier.
Note: The name of an async method, by convention, ends with an "Async" suffix.
The return type is one of the following types:
Task<TResult> if your method has a return statement in which the
operand has type TResult.
Task if your method has no return statement or has a return statement with no operand.
Void if you're writing an async event handler.
The following link provides a good overview of asynchronous programming using async and await:
http://msdn.microsoft.com/en-us/library/hh191443.aspx