0

I'm using .NET Core and trying to figure out why the SQL Server localdb is not working. I am using Dapper to connect to the database and I used breakpoints to check if all the data was there and it was. I get this error when trying to call the ExecuteReader method from the DbCommand class.

My SQL Server connection string is:

"DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=PostStackDatabaseV2;Integrated Security=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"

I use the localdb SQL Server database and tried connecting to it using SQL Server Management Studio and it was successful. The code where I register the user is here:

public int RegisterUser(string connectionStr, string name, string email, string password)
{
    using (IDbConnection conn = new SqlConnection(connectionStr))
    {
        // hash password here before it goes into the database
        var passwordHasher = new PasswordHasher();
        string hashedPassword = passwordHasher.HashPassword(password);

        var isAdmin = 0;
        DateTime currentTime = DateTime.Now;

        conn.Open();

        using (var transaction = conn.BeginTransaction())
        {
            using (DbCommand registerCommand = (DbCommand)conn.CreateCommand())
            {
                try
                {
                    registerCommand.Transaction = (DbTransaction)transaction;
                    registerCommand.CommandText = "INSERT INTO Users VALUES (@UserName, @UserEmail, @UserPassword, @CreatedAt, @Admin)";
                    registerCommand.Connection = (DbConnection)conn;

                    var firstNameParam = registerCommand.CreateParameter();
                    firstNameParam.ParameterName = "@UserName";
                    firstNameParam.Value = name;
                    registerCommand.Parameters.Add(firstNameParam);

                    var emailParam = registerCommand.CreateParameter();
                    emailParam.ParameterName = "@UserEmail";
                    emailParam.Value = email;
                    registerCommand.Parameters.Add(emailParam);

                    var passwordParam = registerCommand.CreateParameter();
                    passwordParam.ParameterName = "@UserPassword";
                    passwordParam.Value = password;
                    registerCommand.Parameters.Add(passwordParam);

                    var createdAtParam = registerCommand.CreateParameter();
                    createdAtParam.ParameterName = "@CreatedAt";
                    createdAtParam.Value = currentTime;
                    registerCommand.Parameters.Add(createdAtParam);

                    var adminParam = registerCommand.CreateParameter();
                    adminParam.ParameterName = "@Admin";
                    adminParam.Value = isAdmin;
                    registerCommand.Parameters.Add(adminParam);

                    int rowsAffected = registerCommand.ExecuteNonQuery();

                    // conn.Close();
                    Console.WriteLine(rowsAffected);

                    int userId = RetrieveUserId(email, connectionStr);

                    return userId;
                }
                catch
                {
                    transaction.Rollback();
                    conn.Close();
                    throw;
                }
            }
        }
    }
}

private int RetrieveUserId(string userEmail, string connectionStr)
{
    using (DbConnection conn = new SqlConnection(connectionStr))
    {
        conn.Open();

        using (var transaction = conn.BeginTransaction())
        {
            using (var retrieveCmd = conn.CreateCommand())
            {
                retrieveCmd.Connection = conn;
                retrieveCmd.Transaction = transaction;
                retrieveCmd.CommandText = "SELECT Id FROM Users WHERE Email = @UserEmail";
                retrieveCmd.CommandType = CommandType.Text;

                retrieveCmd.Parameters.Add(new SqlParameter("@UserEmail", userEmail));

                try
                {
                    var reader = retrieveCmd.ExecuteReader(CommandBehavior.CloseConnection);

                    if (reader.Read())
                    {
                        string userIdStr = reader.GetValue(0).ToString();
                        int userId = int.Parse(userIdStr);

                        if (userId != -1)
                        {
                            // conn.Close();
                            return userId;
                        }
                        else
                        {
                            // conn.Close();
                            return -1;
                        }
                    }
                    else
                    {
                        return -1;
                    }
                }
                catch(DbException err)
                {
                    Console.WriteLine("DbException.GetType: {0}", err.GetType());
                    Console.WriteLine("DbException.Source: {0}", err.Source);
                    Console.WriteLine("DbException.ErrorCode: {0}", err.ErrorCode);
                    Console.WriteLine("DbException.Message: {0}", err.Message);
                    return -1;
                }
                catch(Exception e)
                {
                    Console.WriteLine(e.Message);
                    return -1;
                }
            }
        }
    }
}

RegisterUser is called first which inserts the user's data into the database and the rows affected comes back as 1 instead of 0. When I right-click on the database Users table and clicked "view data" I don't see any data.

The RetrieveUserId method is called to retrieve the user Id generated automatically by SQL Server after the data is inserted. The retrieveCmd.ExecuteReader() line is where the timeout happens. I have tried the dbo. prefix in front of Users in the SQL statement and it didn't work either.

I also tried the async versions of the ExecuteReader and ExecuteNonQuery methods and that didn't work. I am lost as what to do next any help would be greatly appreciated.

Dale K
  • 25,246
  • 15
  • 42
  • 71
Jamar P
  • 11
  • 1
  • 5
  • 1
    Without seeing the code in `RetrieveUserId` I'm only guessing, however: (1) you're opening a transaction in `RegisterUser` to insert a row in `Users`, which will put an update lock on the row/index(es)/table; (2) `RetrieveUserId` is probably opening a second connection to select from `Users` and will be blocking on the lock taken on the first connection. In `RegisterUser` why don't you add a `@UserID` output parameter and add `; select @UserID=scope_identity();` to your `CommandText`? – AlwaysLearning Apr 15 '20 at 22:13
  • Thanks a lot that actually fixed it thank you very much I spent all day on this I appreciate it. – Jamar P Apr 16 '20 at 00:44

0 Answers0