Showing posts with label adonet. Show all posts
Showing posts with label adonet. Show all posts

Monday, March 26, 2012

Problems grasping ado.net - coming from asp background

Hi, i've downloaded a membership and roles provider but i am very new to ado.net. I have come fromasp background. Here's mycode:

public override void AddUsersToRoles(string[] usernames, string[] rolenames) {
// Validate arguments
foreach (string rolename in rolenames) if (!this.RoleExists(rolename)) throw new ProviderException("Role name not found");
foreach (string username in usernames) {
if (username.IndexOf(',') > 0) throw new ArgumentException("User names cannot contain commas.");
foreach (string rolename in rolenames) {
if (IsUserInRole(username, rolename)) throw new ProviderException("User is already in role.");
}
}

SqlConnection db = this.OpenDatabase();
SqlCommand cmd = new SqlCommand("INSERT INTO UsersInRoles (UserName, RoleName) VALUES (@.UserName, @.RoleName)", db);
cmd.Parameters.Add("@.UserName", SqlDbType.VarChar, 100);
cmd.Parameters.Add("@.RoleName", SqlDbType.VarChar, 100);
SqlTransaction tran = null;

try {
tran = db.BeginTransaction();
cmd.Transaction = tran;
foreach (string username in usernames) {
foreach (string rolename in rolenames) {
cmd.Parameters["@.UserName"].Value = username;
cmd.Parameters["@.RoleName"].Value = rolename;
cmd.ExecuteNonQuery();
}
}
tran.Commit();
}
catch {
tran.Rollback();
throw;
}
finally {
db.Close();
}
}

private SqlConnection OpenDatabase() {
SqlConnection DB = new SqlConnection(this.connectionString);
DB.Open();
return DB;
}

The problem i have is that the table structure they provide is to have:

UsersInRoles
- UserName (foreign key to users table)
- RoleName (foreign key to roles table)

but the table structure i have is:

UsersInRoles
- UserID (foreign key to users table)
- RoleID (foreign key to roles table)

So what i need to do is lookup the UserID and RoleID from the appropriate tables based on the UserName and RoleName before doing the insert. However i am not familiar with the new syntax. I'm sure i could bodge something together but i assume this new syntax is something to do with running all the insert statements in one (transaction) so it doesn't have to keep taking round trips back to sqlserver.

Appreciate if someone could show me how this could be done. Thanks

If I understand you correctly, this issue does not differ from ASP to ASP.NET. You need to get UserName(RoleName) based on UserID(RoleID) and then insert the values into UsersInRoles table, right? If so, you can create a stored procedure like this:

CREATE PROCEDURE sp_InsUsersInRoles @.RoleID INT
AS
INSERT INTO UsersInRoles (UserName, RoleName)
SELECT UserName, RoleName
FROM Users join Roles ON Users.RoleID=Roles.RoleID
WHERERoles.RoleID=@.RoleID

Then you can easily call the stored procedure, just remember to set the SqlCommand.CommandType to StoredProcedure, and add parameter for it.

|||

Change:

SqlCommand cmd = new SqlCommand("INSERT INTO UsersInRoles (UserName, RoleName) VALUES (@.UserName, @.RoleName)", db);

to:

SqlCommand cmd = new SqlCommand("INSERT INTO UsersInRoles (UserID, RoleID)SELECT (SELECT UserIDFROM UsersWHERE Username=@.UserName),RoleIDFROM RolesWHERE RoleName=@.RoleName", db);
|||

Hi Motley worked a treat. However i also tried doing:

SqlConnection db = this.OpenDatabase();
SqlCommand cmd = new SqlCommand("INSERT INTO UserRoles (UserName, RoleName) VALUES (@.UserId, @.RoleId)", db);
cmd.Parameters.Add("@.UserId", SqlDbType.Int);
cmd.Parameters.Add("@.RoleId", SqlDbType.Int);
SqlTransaction tran = null;

try {
tran = db.BeginTransaction();
cmd.Transaction = tran;
foreach (string userName in userNames) {
SqlCommand cmd2 = new SqlCommand("SELECT UserId FROM Users WHERE UserName = @.UserName", db);
cmd2.Parameters.Add("@.UserName", SqlDbType.VarChar, 100).Value = userName;
int userId = (int)cmd2.ExecuteScalar();

foreach (string roleName in roleNames) {
SqlCommand cmd3 = new SqlCommand("SELECT RoleId FROM Roles WHERE RoleName = @.RoleName", db);
cmd3.Parameters.Add("@.RoleName", SqlDbType.VarChar, 100).Value = roleName;
int roleId = (int)cmd3.ExecuteScalar();

cmd.Parameters["@.UserId"].Value = userId;
cmd.Parameters["@.RoleId"].Value = roleId;
cmd.ExecuteNonQuery();
}
}
tran.Commit();
}
catch {
tran.Rollback();
throw;
}
finally {
db.Close();
}

but it didn't work.

Any ideas what i did wrong. Cheers

|||

Is RoleName unique within Roles? If you are using the default asp.net membership database structure, then it is not. RoleName is only unique within an Application, and hence may appear in Roles multiple times for different applications. If you have multiple application support, then you will need to supply the application name or application id to your roleid lookup.

My code in this case will add the user to the RoleName of all applications in which the role appears. The same problem is true for UserName as well if you are using multiple applications, but my code will fail in that case as well.

Otherwise I see nothing wrong with your code.

|||

On the other hand, it could be transaction related. I don't normally use the transaction support in ASP.NET. I prefer to use SQL transactions for all my work since I tend to create large batches within my SQL, and wrap that rather than wrapping many SqlCommands. In any case, you might try adding the cmd2 and cmd3 to the transaction as well.

It would also help if you posted what error you are getting rather than just "It didn't work".

|||

Hi, i can't see how to track the error, i'm using visual studio web developer edition. I tried using the built in asp.net config tool to manage my users but when i put a break point in my code it does nothing. However to test if it was reaching this part of the code i did a dummy insert statement and it worked.

I also tried putting an exception on the catch part and doing console.writeline(ex.Message) but that didn't do anything either.

Appreciate your help once more. Thanks

Wednesday, March 21, 2012

Problems connecting to MSDE through ADO.NET

Hi there,
i've installed MSDE and have successfully connected to it from a remote version of Enterprise Manager but when i try to connect using ADO.NET from a website using the same login details i get the following message:
"SQL Server does not exist or access denied"
I installed msde with DISABLENETWORKPROTOCOLS=0 and SECURITYMODE=SQL so everything should be setup properly.
My connection string looks like this:
server=ip_address\instance_name;uid=myusername;pwd=mypassword;database=mydatabase
This connection string works fine when testing locally (without ip address ie. localhost\instance_name)
Any ideas why this doesn't work??You need to check that if the user has accessto the database. For most hosting companies they provide ASPNET useraccount and also NETWORK users. Give permission to ASPNET user and seeif it works also try the same for NETWORK users.

|||Thanks for the reply, you've lost me a bit though. I've setup my own server using Apache and mod_aspdotnet and have successfully tested it remotely from asp.net pages connecting to a MySQL database also on my server. Now i wish to use MSDE and am getting this problem.
How do i setup an ASPNET user account and give it permission to use the database? And why do i need to?
cheers