2010-12-17 10 views
5

Przeprowadzamy migrację do środowiska produkcyjnego i chcę napisać skrypt DBA, który może utworzyć użytkownika z rolami bezpośrednio po uruchomieniu skryptu wygenerowanego przy użyciu aspnet_regsql. W środowisku programistycznym dodawałem użytkowników i role za pomocą interfejsu API dostawcy członkostwa w pliku Global.asax.cs. Ale chcę uniknąć tego zakodowanego podejścia. Teraz pokazuje się mój niedobór T-SQL. Napisałem poniższy skrypt, który działa, jeśli nie uruchomię go od razu.Jak dodać użytkowników i role w SQL dla SQLMembershipProvider?

Use MyApps_Prod; 
GO 

DECLARE @user_identity CHAR(40); 
DECLARE @scalar_userid AS NVARCHAR(255); 
DECLARE @scalar_roleid AS NVARCHAR(255); 
DECLARE @app_id AS NVARCHAR(255); 
SET @user_identity = N'AMERICAS\First.Last'; 

SET @app_id = (SELECT DISTINCT ApplicationId 
      FROM [dbo].[aspnet_Applications] 
      WHERE loweredapplicationname = 'MyApplication'); 
SELECT * FROM [dbo].[aspnet_Users] WHERE UserName = @user_identity 

IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Users] WHERE UserName = @user_identity) 
BEGIN 
    INSERT INTO [dbo].aspnet_Users 
      ([ApplicationId], [UserName], [LoweredUserName], [LastActivityDate]) 
    VALUES 
     (@app_id, @user_identity, LOWER(@user_identity), GETDATE()); 
END; 

DECLARE @role_name CHAR(40); 
SET @role_name = N'Communicator'; 
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Roles] WHERE RoleName = @role_name) 
BEGIN 
    INSERT INTO [dbo].[aspnet_Roles] 
     ([ApplicationId], [RoleName], [LoweredRoleName]) 
    VALUES 
     (@app_id, @role_name, LOWER(@role_name)) 
END; 


SET @scalar_userid = (SELECT DISTINCT UserID FROM [dbo].aspnet_Users WHERE UserName = @user_identity); 
SET @scalar_roleid = (SELECT DISTINCT RoleID FROM [dbo].aspnet_Roles WHERE RoleName = @role_name); 

INSERT INTO [dbo].aspnet_UsersInRoles (UserID, RoleID) 
    VALUES (
     @scalar_userid , 
     @scalar_roleid 
    ); 


SET @role_name = N'AccessAdministrator'; 
IF NOT EXISTS (SELECT * FROM [dbo].[aspnet_Roles] WHERE RoleName = @role_name) 
BEGIN 
    INSERT INTO [dbo].[aspnet_Roles] 
     ([ApplicationId], [RoleName], [LoweredRoleName]) 
    VALUES 
     (@app_id, @role_name, LOWER(@role_name)) 
END; 


SET @scalar_roleid = (SELECT DISTINCT RoleID FROM [dbo].aspnet_Roles WHERE RoleName = @role_name); 

INSERT INTO [dbo].aspnet_UsersInRoles (UserID, RoleID) 
    VALUES (
     @scalar_userid , 
     @scalar_roleid 
    ); 
GO 

Odkryłem, że mogę dostać się do pracy, jeśli INSERTs kończę każdy INSERT średnikiem, a następnie dodać GO, ale potem muszę redeclare i przypisanie każdej zmiennej.

Jak zrobiłby to prawdziwy programista SQL?

+0

Jeśli wszystko inne zawiedzie, pozostaw go w pliku global.asax dla wersji 1 i usuń go dla wersji 2. – Greg

Odpowiedz

10

Zamiast ręcznie pisać instrukcje INSERT, należy użyć procedur przechowywanych, które są częścią dostawcy implementacji SqlMembershipProvider i które są dołączane podczas instalowania usług aplikacji przy użyciu narzędzia aspnet_reg.exe.

W szczególności, należy:

  • aspnet_Roles_CreateRole aby utworzyć nową rolę
  • aspnet_Membership_CreateUser aby utworzyć użytkownika i podać jego dane członków (hasło, pytanie bezpieczeństwa i odpowiedź, i tak dalej)
  • aspnet_UsersInRoles_AddUsersToRoles aby dodać istniejącego użytkownika do istniejącej roli

Tylko jeden trudny do wyrzucenia z obiektu jest . Zakładając, że twoje hasła nie są zapisane w postaci zwykłego tekstu, musisz przekazać do sproca wersję zaszyfrowaną lub zakodowaną za pomocą parametru @Password.Sugeruję użycie Reflectora do zbadania kodu w klasie CreateUser method klasy SqlMembershipProvider. Tam zobaczysz, jak .NET obsługuje tę logikę pod okładkami.

Jako alternatywę dla skryptów, rozważ napisanie programu wiersza poleceń, który może odczytuje plik tekstowy i tworzy określone role i użytkowników oraz powiązania roli użytkownika. Ten program wiersza poleceń używałby bezpośrednio interfejsu API programu Membership i dlatego obsługiwałby wszystkie szczegóły niskiego poziomu. Następnie można uruchomić ten program wiersza poleceń w ramach procesu budowania lub wdrażania.

Happy Programming!

+0

Podoba mi się sugestia wiersza polecenia. – Greg

+0

To działało jak czar. Dzięki. – Blanthor

2

Czy próbowałeś już uruchomić swoją zakodowaną implementację za pomocą programu SQL Profiler? To powinno pokazywać dokładną kolejność uruchamiania rzeczy.

+0

Spróbuję dzięki. – Blanthor

+0

Powinieneś przynajmniej użyć przechowywanych procedur zawartych w bazie danych, jeśli możesz. Profiler powinien pokazać, jak z nich korzystać. – Greg

+0

+1 To było bardzo pomocne dzięki. – Blanthor

0

"Jak zrobiłby to prawdziwy programista SQL?"

Oto początek. Chociaż T-SQL nie obsługuje bezpośrednio tablic, zazwyczaj przechodzę do nich przez zmienne tabel, traktując je jako tablice, w celu skondensowania/ponownego użycia kodu. W twoim przykładzie nie jest to ogromna korzyść. Ale gdyby było 10 nazw ról, byłby.

Przykład:


DECLARE @roles TABLE (rolename CHAR(40)); 
INSERT @roles 
SELECT 'Communicator' 
UNION ALL 
SELECT 'AccessAdministrator'; 
DECLARE @rolename CHAR(40); 

--loop through the @roles table variable like it's an array 
WHILE (SELECT COUNT(*) FROM @roles) > 0 
    BEGIN 
    SELECT TOP 1 @rolename = rolename FROM @roles; 
    --Do something with the current rolename 
    SELECT @rolename; 
    DELETE @roles WHERE rolename = @rolename; 
    END 
0

To nie jest dobry pomysł stworzenia go przez skrypt. Ponadto nie jestem pewien, kiedy mówisz, że musisz tworzyć ręcznie, jeśli używasz API. Czy próbujesz przenieść swoje istniejące dane?

Ale jeśli to jest wybór, proponuję użyć narzędzia reflektora, aby zobaczyć kod tych metod członkostwa/ról. Uruchomienie przechowywanego procesu nie jest wystarczające, ponieważ może istnieć szyfrowanie/haszowanie, wybieranie właściwego parametru applicationName i kilka innych kontroli, jak to się dzieje w pliku web.config, zanim przechowywany proces zostanie wykonany za pomocą tych metod API.

Pamiętaj więc o tych wszystkich, ponieważ będziesz mógł wstawiać dane użytkownika, ale kiedy zechcesz z niego skorzystać, użyjesz API, co może popsuć coś innego.

Powiązane problemy