3

둘 중 매우 가깝게 실행될 때 실패하는 일부 SSRS 보고서가 있습니다.SSRS 코드 공유 변수 및 동시 보고서 실행

SSRS 보고서의 두 인스턴스가 동시에 실행되는 경우 클래스 수준 (함수 내에 있음)에서 선언 된 모든 코드 변수가 충돌 할 수 있음을 알았습니다. 이것이 보고서 실패의 원인이 될 수 있다고 생각하며 잠재적 인 문제를 해결하기 위해 노력하고 있습니다.

우리가 SSRS의 코드 부분을 전혀 사용하지 않는 이유는 맞춤 그룹 및 페이지 헤더 계산과 같은 것들입니다. 이 코드는 TextBoxes의 표현식에서 호출되며 현재 레이블이 있어야하는 내용을 반환합니다. 코드는 알 수 없을 때 마지막 헤더 값이 무엇인지 기억하거나 재사용을 위해 새 헤더 값을 저장하기 위해 상태를 유지해야합니다.

참고 : 여기 내 자원 변수 충돌 문제에 대한 있습니다

MSDN SSRS Forum : 두 사람이 동일한 순간에 보고서를 실행하면

이 정적 변수를 사용하기 때문에이하는 거기 (SQL 2000에서는 두 명의 사용자가 동일한 동시 실행으로 인해 에서 동일한 보고서를 통해 페이지 매김을하는 경우가 종종 발생할 수 있습니다). 이 문제를 피하려면 을 100 % 정확하게 사용해야하는 경우 사용자 ID (Globals! UserID)를 기반으로 각 공유 변수를 해시 테이블로 만들 수 있습니다.

Embedded Code in Reporting Services :

... 여러 사용자가 동시에이 코드를 사용하여 보고서를 실행하는 경우, 두 보고서가 공유되는 이유입니다 (같은 수 필드를 변경합니다 들). 이러한 종류의 상호 작용을 디버깅하지 않으려면 로컬 변수 (ByVal를 전달하거나 함수 본문에 선언 된 변수) 만 사용하여 공유 함수에 고정하십시오.

보고서 생성 서버에서 보고서가로드되고 코드 모듈이 정적 클래스라는 생각이 듭니다. 두 번째 클라이언트가 동일한 보고서를 다른 보고서와 신속하게 요청하면 해당 정적 클래스의 동일한 인스턴스에 연결됩니다. (이 문제가 잘못되면 내 설명을 수정할 수 있습니다.)

그래서 해시 테이블을 사용하여 격리 된 상태로 유지할 생각이었습니다. 해시 키를 InstanceID라는 내부 보고서 매개 변수 기본값 인 =Guid.NewGuid().ToString()으로 계획하고있었습니다.

내 연구를 통해이 방법을 사용했지만 해시 테이블이 스레드로부터 안전하지 않기 때문에 더 복잡하다는 것을 발견했습니다 (Maintaining State in Reporting Services).

필자는 내가 개발 한 것과 비슷한 코드를 가지고 있으며, 스레드로부터 안전한 전체 내용은 완전히 내 경험 밖에 있습니다. 이 모든 것을 연구하고 내가 확신하고 잘 수행 할 수있는 합리적인 코드를 작성하는 데 몇 시간이 걸릴 것입니다.

내가 너무 멀기 전에, 다른 누군가가 이미이 길을 걸어 왔는지에 대해 궁금해하고 있습니다.여기에 지금까지 가지고있는 코드는 : 여기

Private Shared Data As New System.Collections.Hashtable() 

Public Shared Function Initialize() As String 
    If Not Data.ContainsKey(Parameters!InstanceID.Value) Then 
     Data.Add(Parameters!InstanceID.Value, New System.Collections.Hashtable()) 
    End If 
    LetValue("SomethingCount", 0) 
    Return "" 
End Function 

Private Shared Function GetValue(ByVal Name As String) As Object 
    Return Data.Item(Parameters!InstanceID.Value).Item(Name) 
End Function 

Private Shared Sub LetValue(ByVal Name As String, ByVal Value As Object) 
    Dim V As System.Collections.Hashtable = Data.Item(Parameters!InstanceID.Value) 
    If Not V.ContainsKey(Name) Then 
     V.Add(Name, Value) 
    Else 
     V.Item(Name) = Value 
    End If 
End Sub 

Public Shared Function SomethingCount() As Long 
    SomethingCount = GetValue("SomethingCount") + 1 
    LetValue("SomethingCount", SomethingCount) 
End Function 
  1. 나의 가장 큰 관심사는 스레드 안전입니다. 나는 아래 질문의 나머지 부분을 이해할 수 있을지도 모르지만 나는 이것에 대해 경험이 없다. 그리고 나는 잘못 입력하는 것이 쉽다는 것을 안다. 위의 링크는 방법 Dim _sht as System.Collections.Hashtable = System.Collections.Hashtable.Synchronized(_hashtable)을 사용한다. 그게 최고야? 뮤텍스는? 신호기? 나는 이것에 대한 경험이 없다.

  2. Hashtable의 System.Collections 네임 스페이스가 맞지만 System.Collections를 내 보고서의 참조로 추가하여 "파일 또는 어셈블리를로드 할 수 없습니다."시스템의 현재 오류를 치료하는 데 문제가 있다고 생각합니다. . 수집 ''. 참조를 추가하기 위해 찾아 볼 때 사용할 수있는 구성 요소가 아닙니다.

  3. 매개 변수의 기본값 식에서 코드를 호출 할 수 있다는 것을 확인 했으므로 여기에 Initialize 코드를 넣을 것입니다. 또한 OnInit 절차에 대해서도 알게되었지만 연구하고 해결할 자체 문제가 있습니다 : the Parameters collection may not be referenced from the OnInit method during parameter initialization.

  4. 데이터 변수를 New로 선언하는 것이 확실하지 않습니다. 이미 완료되지 않은 경우에만 초기화 도구에서 인스턴스화해야합니다 (하지만 빈 상태인지 확인하는 사이의 지연 때문에 경쟁 조건이 걱정됩니다. 인스턴스화).

  5. 공유 키워드에 대한 질문이 있습니다. 모든 경우에 필요합니까? 함수 선언을 무시하면 오류가 발생하지만 은 변수 선언을 그대로두면 작동하려면이 표시됩니다. 여러 개의 동시 보고서 실행을 테스트하는 것은 어렵습니다 ... SSRS 코드의 맥락에서 Shared가 구체적으로 무엇을 의미하는지 설명 할 수 있습니까?

  6. 변수를 초기화하는 더 좋은 방법이 있습니까? 변수가 해시 테이블에 아직 존재하지 않는다는 것을 발견하면 사용할 기본값 인 GetValue 함수에 두 번째 매개 변수를 제공해야합니까?

  7. 내 구현에서 선택한대로 중첩 해시 테이블을 사용하거나 플랫 해시 테이블을 갖기 위해 내 InstanceID를 변수 이름과 연결하는 것이 더 좋습니까?

내가 여기 제시 한 모든 측면에 대한 지침, 아이디어 및/또는 비평을 정말 고맙게 생각합니다.

감사합니다.

에릭

+0

한 번에 질문이 너무 많습니까? 대신 7 가지 질문을 게시해야합니까? – ErikE

+0

질문이 현지화되었습니다. 아무도 ** 귀하 ** 코드에 대한 경험이 없습니다.변수에 문제가있는 경우 "충돌없이 SSRS에서 변수를 사용하는 방법"을 묻습니다. –

+0

은 모든 것을 읽지는 않았지만 보고서를 캐싱하려고 시도 했습니까? – DForck42

답변

1

코드는 잘 보인다. 스레드 안전성을 위해서만 루트 (공유) 해시 테이블 데이터 만 동기화해야합니다. InstanceID를 사용하지 않으려면 Globals.ExecutionTimeUser.UserID을 연결할 수 있습니다.

Private Shared Data As System.Collections.Hashtable 

If Data Is Nothing Then 
    Set Data = Hashtable.Synchronized(New System.Collections.Hashtable()) 
End If 

포함 된 해시 테이블은 어쨌든 한 번에 하나 개의 스레드가 사용되어야하지만 의심하는 경우, 당신도 동기화 할 수 있습니다 :

는 기본적으로 난 그냥 이런 식으로 초기화 변경할 생각합니다.

+0

도움에 감사드립니다. 그것은 합리적으로 들린다. – ErikE