Error when converting a synchronous method to an asynchronous method [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 days ago.
Improve this question
I am trying to convert this block of code to Async
public static List<Employee> EmployeesList()
{
List<Employee> list = new List<Employee>();
DataTable dt = new DataTable();
dt = Data.DataAccess.ExecuteDataTable("[Employee].[dbo].[Employee_Select]");
foreach (DataRow row in dt.Rows)
{
list.Add(new Employee()
{
Id = Convert.ToInt32(row["ID"]),
Name = Convert.ToString(row["Name"]),
Email = Convert.ToString(row["Email"]),
Age = Convert.ToInt32(row["Age"]),
Salary = Convert.ToInt32(row["Salary"])
});
}
return list;
}
The modified code looks like this
public static async Task<List<Employee>> EmployeesList()
{
List<Employee> list = new List<Employee>();
DataTable dt = new DataTable();
dt = await Data.DataAccess.ExecuteDataTableAsync("[Employee].[dbo].[Employee_Select]");
foreach (DataRow row in dt.Rows)
{
list.Add(new Employee()
{
Id = Convert.ToInt32(row["ID"]),
Name = Convert.ToString(row["Name"]),
Email = Convert.ToString(row["Email"]),
Age = Convert.ToInt32(row["Age"]),
Salary = Convert.ToInt32(row["Salary"])
});
}
return list;
}
Edit for clarity. The synchronous method returns a list. The asynchronous method does not (It just exits the block and skipping the break points under the await), which causes a null reference error further down the path. Why isn't my Asynchronous method returning any results?
Ignore this part from the original post.
The problem I am having is that my async code block seems to be exiting before the data is returned because the Razor page gives me an Object reference not set to an instance of an object error on my Model.Employees. What am I doing wrong?

What is your calling code to this method?
Once you enter into async\await, you need to await all the calling methods.
You need to await EmployeeList(). Otherwise the calling method prematurely given control and your list is always null.
Hope this helps

Related

Declare a variable per thread and manage them in c# Parallel.Foreach [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm writing a code to iterate through a huge list of objects in order to persist them in DB.
I have a counter wich is increasing with each iteration and when it reaches 500 I persist all in DB (from a StringBuilder).
If I do it sequential I have no problems, but it takes a long time. That's why I want to do it with parallelism.
With parallelism I've seen I cannot have one StringBuilder for all threads, so I need to create one for each thread.
My questions are:
How can I create a StringBuilder per thread?
And then, How can I persist all StringBuilder objects to DB and empty them all when the static counter reaches 500 loops?
I have the following code:
int counter = 0;
Parallel.ForEach(myList, element =>
{
lock (balanceLock)
{
counter++;
}
var sb = new StringBuilder(); //I need one StringBuilder for thread, not for iteration
...
if (decimal.Remainder(counter, 500) == 0)
lock (balanceLock)
{
persistInDB(sb.toString());
sb.Clear();
}
});
Finally I solved it in a sequential way, by putting the records in a table and making a SqlBulkCopy against the DB, following the advices.
DataTable table = getDataTable();
myList.ForEach(element => {
//...
table.Rows.Add(getRow(element));
if (decimal.Remainder(counter, 500) == 0){
SqlConnection _db;
_db.Open();
using (SqlBulkCopy bulk = new SqlBulkCopy(_db)){
var map1 = new SqlBulkCopyColumnMapping("columnName1", "columnName1");
var map2 = new SqlBulkCopyColumnMapping("columnName2", "columnName2");
//...
bulk.ColumnMappings.Add(map1);
bulk.ColumnMappings.Add(map2);
//...
bulk.DestinationTableName = "DestinationTableName";
bulk.WriteToServer(table);
bulk.Close();
}
}
}

Create a dictionary in c# through lambda [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a following code:
var dict = new Dictionary<byte?, List<Id>>();
foreach (var record in Records)
{
if(record.SubId.HasValue)
{
dict.Add(SubIdsDictionary[record.SubId.Value], new List<Record> { record });
}
else
{
dict.Add(IdsDictionary[record.Id.Value], new List<Record> { record });
}
}
Records is the list of records for one name.In this record class I have Id,SubId and Companyname. Each name have id as mandatory but subid is not.So,if name has subid then I have to give priority to subid and first get the new sub id from the dictionary SubIdsDictionary(because subid is key in ref dict SubIdsDictionary) and make the new subid as key and the whole record as value in the new Dictionary dict. But if name dont have subid then i will use id and first get the new id from reference dict IdsDictionary and make the new id as key and value will be whole record.
Now in the new dictionary keys will be mix of ids and subids and record will be value as List
Can someone help me to convert this code through lambda?
You can use ToDictionary method from Linq.
It should looks like this:
var dict = Records.ToDictionary(
r => (r.SubId.HasValue ? SubIdsDictionary[r.SubId.Value] : IdsDictionary[r.Id.Value]),
r => new List<Record> {r}
);

how i can get the data that stored in list [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I want to generate a random number from first list (list of Object) and put it in the second list to get a random connection id to make connection between the original id and the random id how I can get the item from the first list by index and of which type I have to cast it
public class OneHub :Hub
{
static List<UserId> ConnectedUser = new List<UserId>();
static List<MessageDetail> CurrentMessage = new List<MessageDetail>();
static List<ConnectionsId> Connection = new List<ConnectionsId>();
public void Connect(string id)
{
if (ConnectedUser.Count(x => x.ConnectionId == id) == 0)
{
ConnectedUser.Add(new UserId { ConnectionId = id });
if (ConnectedUser.Count != 0 || ConnectedUser.Count != 1)
{
Random r = new Random();
int x = r.Next(0,ConnectedUser.Count);
(object)ConnectedUser.item[x];
Connection.Add(new ConnectionsId {ConnectionId=id,ConnectionId2= })
}}}
First off, you're going to need to make sure that the ConnectedUser that you randomly get is not the same user you are linking to, before you add that connection, or you're going to find further issues.
For ConnectedUser, you can get the index by simply using ConnectedUser[x]. (I suggest making your lists plural so it's obvious that they're collections.)
You need to assign that connected user to a new object.
Something like
UserID linkedUser = ConnectedUser[x];
This way, you can reference linkedUser.ConnectionId in your connection addition.
Alternately, you could just use:
Connection.Add(new ConnectionsId { ConnectionId = id, ConnectionId2 = ConnectedUser[x].ConnectionId };
This random setup, though, does have a strong potential for having several people ending up not linked to anyone. Additionally, your line that states:
if (ConnectedUser.Count != 0 ...
is redundant. You just added a user to that list. It should never be of size 0.

Is there any alternate way of avoiding the Foreach loop? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Please look into the below code
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<Employee> employeeCollection = new List<Employee>();
for (int i = 1; i < 10; i++) employeeCollection.Add(new Employee {
EmployeeID = i,
EmployeeName = string.Concat("Employee", i),
Email = string.Concat("Email", i) });
//loop thru every record
foreach (Employee e in employeeCollection)
{
SendEMail(e);
}
}
private static void SendEMail(Employee employee)
{
// do something
}
}
class Employee
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string Email { get; set; }
}
}
I have to do some operation on every record of the Employee. Henceforth, I am using the foreach loop. If the number of records increases, the number of operations will equally increase. So it will be O(N).
Is there any better approach for this?
N.B.~ I am not looking for .foreach()
Don't bother about O(N). Simple algorithmic complexity is rarely a good answer regarding real-life performance. The expensive part isn't iterating over the employee list, it's sending an e-mail.
If allowed by your requirements, you could use a single e-mail with multiple recipients, for example - of course, this will only work if all the e-mails are the same. Otherwise, on some level, you just have to send n separate e-mails.
Of course, there's still a lot of ways to improve the perceived performance even then. You could queue all the e-mails at once, and show the user they're waiting in a queue, rather than blocking the UI. You could send each of the e-mails in parallel. You could send the e-mails to a different service (e.g. Microsoft Exchange) to handle the actual sending for you.
In the end, though, if you're sending 100 different e-mails, you have to send 100 e-mails. No clever algorithm will help you.
what Luaan is saying is right.
But just to simplify your code, you can send email while adding employee in employeeCollection , you need not have to loop employeeCollection again to send email.
Something like this.
for (int i = 1; i < 10; i++)
{
var emp = new Employee
{
EmployeeID = i,
EmployeeName = string.Concat("Employee", i),
Email = string.Concat("Email", i)
};
employeeCollection.Add(emp);
SendEMail(emp);
}

How to insert values in one column? c# [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have the following code:
foreach (string value in data1)
{
var match = Regex.Match(value, #"(?<Number>\d+)(?<Text>.*)");
var number = match.Groups["Number"].Value;
var text = match.Groups["Text"].Value;
string result2 = string.Format("{0}", text);
data.Rows.Add(result2);
dataGridView1.DataSource = data;
}
This code will add the data to my first column. How do i fix it to make that data to be added to the second column instead?
I would think you need move the line of binding datasource out of the loop block firstly,
foreach (string value in data1)
{
var match = Regex.Match(value, #"(?<Number>\d+)(?<Text>.*)");
var number = match.Groups["Number"].Value;
var text = match.Groups["Text"].Value;
string result2 = string.Format("{0}", text);
data.Rows.Add(result2);
}
dataGridView1.DataSource = data;
DataColumn Col = datatable.Columns.Add("Column Name", typeof(Boolean));
Col.SetOrdinal(0);
DataRow newRow = data.NewRow();
newRow["Text"] = text; //if the column name is Text
data.Rows.Add(newRow);

Categories