2014-11-08 3 views
0

데이터베이스에서 CRUD 작업을 수행하기 위해 Entity Framework를 사용하는 웹 응용 프로그램을 작성했습니다.저장 프로 시저를 올바르게 사용하기

저장 프로 시저가 CUD 작업에 사용되도록이 값을 변경하려고합니다. 나는 다른 프로젝트에서 Stored Procedures를 광범위하게 사용했지만; 주위를 읽은 후에, 나는 Stored Procedures가 비즈니스 로직을 포함해서는 안되는 생각의 학교가 있다는 것을 알 수있다.

Stored Procs로 응용 프로그램을 만들 때이 접근법을 사용하는 사람이 있습니까? 이 방법이 효과가 있습니까? 이 접근 방식이 정확하다고 가정하면 Stored Procs는 기본 CRUD 작업 만 수행해야한다고 가정합니다.

또한 - 내 웹 응용 프로그램은 관리자가 개별 사용자에게 개별 암호에 대한 액세스 권한을 부여 할 수있는 암호 공유 시스템입니다. 따라서 암호가 만들어지면 Stored Proc는 데이터베이스에 암호를 쓰고 관리자는 암호에 대한 액세스 권한을 자동으로 부여 받아야합니다. 따라서 Add_Password SP에 일부가 포함되어 있으면 "SP에서 업무 로직을 떠나십시오" 관리자가 액세스 할 수 있도록 관련 레코드를 작성하는 논리 또는 Add_Access SP를 호출하는 루프를 통해 수행해야합니까?

답변

2

기술적 인 주제와 마찬가지로 Idealism, Pragmatism 또는 Ignorance를 기반으로 한 광범위한 의견이 있습니다. 커서를 사용하는 것이 괜찮은지 물어 보면 오히려 빨리 볼 수 있습니다 :).

나는 "비즈니스 논리"가 "데이터 논리"라고 부르는 것과는 별도로 실제 비즈니스 논리를 정확히 구성하는 것을 구분하는 시간이 상대적으로 거의없는 것처럼 보이기 때문에 "비즈니스 논리 없음"이라는 것이 가장 이상하다고 생각합니다. Data Logic은 RDMBS를 사용하여 효율적으로 데이터를 조작합니다.

필자는 좀 더 실용적인 접근법을 사용하여 실제로 수행중인 작업과 그 작업을 가장 효율적으로 수행하는 작업을 살펴 ​​봅니다. 루프를 통해 proc 나 app ​​레이어에서 관련 레코드를 지정하는 특별한 경우에는, 한 줄 주석으로는 할 수 없었던 것을 얻지 못했을 때 앱 레이어에서 그런 일을하는 것은 어리석은 일이라고 생각합니다 그러나 반복 된 데이터베이스 호출을하려면 막대한 비용이 듭니다. 물론 루프 된 호출을 트랜잭션으로 랩핑하고 동일한 연결을 사용하면 비용이 절감 될 수 있지만 스토어드 프로 시저의 간단한 세트 기반 명령문처럼 효율적이지는 않습니다.

틀린 말은하지 마세요. 알고리즘은 앱 레이어에 있어야한다는 것에 동의하지만 일단 데이터를 유지해야한다면 DB에 전달하여 작업을 수행해야합니다. 다만 수행 응용 프로그램 코드에서

CREATE PROCEDURE dbo.Add_Password 
(
    @UserID  INT, 
    @Password  NVARCHAR(50), 
    @PasswordID INT OUTPUT = -1 
) 
AS 
SET NOCOUNT ON; 

BEGIN TRY 

    BEGIN TRAN; 

    INSERT INTO dbo.Passwords (UserID, [Password]) 
    VALUES (@UserID, @Password); 

    SET @PasswordID = SCOPE_IDENTITY(); 

    INSERT INTO dbo.PasswordAccess (UserID, PasswordID) 
     SELECT usr.UserID, @PasswordID 
     FROM dbo.Users usr 
     WHERE usr.UserType = 1; -- Assuming 1 = Admin 

    COMMIT TRAN; 

END TRY 
BEGIN CATCH 
    ROLLBACK TRAN; 

    THROW; 
END CATCH; 

: 예를 들어

, 당신의 Add_Password 시저 같은 것을 할 수

// Insert new password and assign access to all Admin-level Users (i.e. UserType = 1) 
SqlCommand.ExecuteNonQuery(); 

모든 응용 프로그램 계층에서 이렇게 의미 "의 모든 점점 Admin "사용자 ID와 각각 AddAccess을 호출 하시겠습니까? 그것은 비효율적 일뿐만 아니라 복잡하게 보입니다.

일반적으로 DB에서 과 같은 "데이터 로직"(예 : 위 예제와 같이)을 수행하려고 시도하지만은 "DB의 비즈니스 로직 없음"이라는 이상에 걸리지 않습니다. 당신은 DB에 그 중 일부를 넣는 것에서 진정으로 이익을 얻는 상황이 있다면 당신의 프로젝트가 어려움을 겪게합니다.DB 호출에서 어떤 일이 일어나고 있는지에 대한 앱 코드의 설명 (정보/세부 사항이 충분한 유용한 주석과 신비가 아닌 실제 아이디어를 전달하는 세부 정보)을 꼭 입력해야합니다.

편집 : 이러한 유형의 작업에 대한 완성도를 위해서
,이 새로운 무언가를 추가하는 시간이있다, 그러나 협회의 목록은 응용 프로그램 계층에서가 아니라 데이터베이스에 수집에 저장 . 다음 PasswordID을 반환하는 AddPassword 저장 프로 시저를 호출하고 AddAccessPasswordID이고 한 번에 UserID이 전달되는 Admins 컬렉션을 루프에서 사용하면됩니까? 대답은 여전히 ​​"아니오"입니다. 이 경우 Admins 컬렉션을 순환하여 CSV 문자열 또는 특성 기반 XML 문서를 저장 프로 시저로 전달할 수 있습니다. 컬렉션에서 추출한 ID 목록이 커지면 (즉, 100,000 개가 넘는 항목) TVP (테이블 반환 매개 변수)가 더 효율적일 수 있지만 작은 목록의 경우 TVP 은 오버 엔지니어링 ()이 될 수 있습니다 분명히 각 상황에 가장 적합한 것을하십시오). 나는 이상적인 세계는 구성 형태의 일종의으로 비즈니스 로직의 대부분을 원하는 것이 믿는

CREATE PROCEDURE dbo.Add_Password 
(
    @UserID  INT, 
    @Password  NVARCHAR(50), 
    @AdminIDs  VARCHAR(MAX), -- CSV list of UserIDs that are Admin/UserType = 1 
    @PasswordID INT OUTPUT = -1 
) 
AS 
SET NOCOUNT ON; 

BEGIN TRY 

    BEGIN TRAN; 

    INSERT INTO dbo.Passwords (UserID, [Password]) 
    VALUES (@UserID, @Password); 

    SET @PasswordID = SCOPE_IDENTITY(); 

    INSERT INTO dbo.PasswordAccess (UserID, PasswordID) 
     SELECT split.[Value], @PasswordID 
     FROM dbo.SqlClrOrXmlStringSplitter(@AdminIDs, ',') split; 

    COMMIT TRAN; 

END TRY 
BEGIN CATCH 
    ROLLBACK TRAN; 

    THROW; 
END CATCH; 
+1

굉장한 답변, 고마워요. – binks

+0

@binks : 언제든지 :). TRY/CATCH 및 트랜잭션 처리 기능이 있어야하므로 SQL을 약간 업데이트했습니다. 또한 EDIT 섹션을 추가하여보다 선명한 그림을 그려 낼 수 있습니다. Upvote? : D –

+1

+1 이러한 상세한 대답을 위해, 누군가가 당신을 위해 당신의 문제를 해결하기 위해이 많은 시간을 보낸다면, 그 사람은 upvote를받을 자격이 있으며, 그것은 사람들이 질 높은 응답을 제공하도록 장려합니다. –

0

: 따라서, 위의 예 PROC 뭔가처럼 약간 변경합니다. SP 자체는 최종 사용자에게는 구성 가능하지 않지만 구성 정보가 포함 된 개체를 호출 할 수 있습니다. 때로는 요구 사항에 따라 비즈니스 논리를 SP에 포함시키는 것이 합리적이며, 그렇게함으로써 위반하는 법도 없습니다.

관리자가 항상 암호를 확인해야하는 경우 암호에 대한 액세스 권한을 부여하는 대신 다른 방법이있을 수 있습니다. 액세스는 항상 사용자 유형에 암시적일 수 있으므로 액세스를 추가하기 위해 호출 할 필요가 없습니다. 관리자에 대한 액세스가 선택적인 경우 테이블의 설정 정보를 잘 구성 할 수 있습니다.

기존 시스템을 개선 한 경우 저장 프로 시저에서 액세스를 추가하는 방법이 잘 될 것이라고 확신하지만이 기능을 더 모듈화되도록 분리하는 아이디어를 좋아합니다. 다른 SP에 대한 호출이 제대로 작동하거나 시스템의 특성에 따라 트리거에서 업데이트 될 수 있습니다.

관련 문제