The following code is from the DataAccess layer that calls the SQL stored procedure and returns the result set back to the calling code.public class CoffeeDataAccess : ICoffeeDataAccess    {        private readonly Database coffeeDatabase;        public CoffeeDataAccess(ICoffeeShopDatabaseFactory factory)        {            this.coffeeDatabase = factory.GetCoffeeDatabase();        }        public async Task<IEnumerable<Coffee>> GetAllAvailableCoffees()        {            IEnumerable<Coffee> coffees = await this.ExecuteCommandAsync(spGetAllCoffees);            return coffees;        }        public async Task<IEnumerable<Coffee>> GetCofeesOfTheWeek()        {            IEnumerable<Coffee> coffees = await this.ExecuteCommandAsync(spGetCoffeesOfTheWeek);            return coffees;        }        private async Task<IEnumerable<Coffee>> ExecuteCommandAsync(string spName)        {            IList<Coffee> coffees;            using (DbCommand command = this.coffeeDatabase.GetStoredProcCommand(dbo + spName))            {                Task<IDataReader> dataReaderTask =                    Task<IDataReader>.Factory.FromAsync(this.coffeeDatabase.BeginExecuteReader, this.coffeeDatabase.EndExecuteReader, command, null);                using (IDataReader reader = await dataReaderTask)                {                    coffees = new List<Coffee>();                    while (reader.Read())                    {                        Coffee c = new Coffee();                        c.Id = int.Parse(reader[ID].ToString());                        c.Name = reader[Name].ToString();                        c.ShortDesc = reader[ShortDesc].ToString();                        c.LongDesc = reader[LongDesc].ToString();                        c.Price = decimal.Parse(reader[Price].ToString());                        c.ImageUrl = reader[ImageUrl].ToString();                        c.ImageThumbnailUrl = reader[ImageThumbnailUrl].ToString();                        c.CategoryId = int.Parse(reader[CategoryId].ToString());                        coffees.Add(c);                    }                }            }            return coffees;        }    }The CoffeeDataAccess object is newly instantiated every time when a client code asks for it from the IoC container (registered as Trasient in ASP.NET Core - startup class). Is the method name ExecuteCommandAsync thread safe or not?I think it is because each time a new instance of the CoffeeDataAccessclass is created but I'm not sure.
Accessing SQL stored procedures
c#;thread safety
Unless factory.GetCoffeeDatabase(); returns a shared factory I cannot see any problems. On the Reader reader.GetInt32(0); is more efficient.  There are direct calls for all the data type.Assigning property by property is fine.  I think passing in a constructor is cleaner.