2009-07-17 4 views
0

.Net 웹 응용 프로그램에 Windows 워크 플로를 구축하고 있습니다. 내가 가진 문제는 상태 머신에서 활동을 추가 또는 제거하거나 변경하고 다시 컴파일하고 실행 할 때마다 더 이상 추적 및 지속성을 위해 데이터베이스에있는 것과 일치하지 않는다는 것입니다. 변경 내용을 업데이트하거나 데이터베이스에 새 버전의 워크 플로를 만드는 대신 오류가 발생합니다. 때로는 "범위를 벗어난 인덱스"오류가 발생하며 다른 경우에는 "멤버 XXXXX를 가져올 수 없습니다."내 Windows 워크 플로를 변경할 때마다 데이터베이스를 다시 작성하지 않는 방법은 무엇입니까?

작동 시키려면 데이터베이스를 삭제하고 다시 빌드해야합니다. 워크 플로 엔진이 데이터베이스의 워크 플로를 찾을 때 워크 플로 엔진이 워크 플로를 찾지 않고 데이터베이스에 추가하기 때문에 이것이 효과가 있다고 생각합니다. 워크 플로를 구축하고 하루에 여러 번 변경되는 현재 무대에서 매우 실망 스럽습니다.

워크 플로 엔진에서 데이터베이스의 관련 테이블을 워크 플로의 변경 사항으로 업데이트하는 방법이 있습니까? 또는 새 버전으로 덮어 씁니까? 런타임시 동적 업데이트를위한 워크 플로 설정에 대한 여러 웹 페이지를 살펴 보았지만이 제안 중 어느 것도 나에게 도움이되지 못했습니다. 그리고 이것이 제가 워크 플로우에 대해 원하는 기능인 반면, 실제로 문제를 해결할 수있는 방법인지는 확실하지 않습니다. 워크 플로의 새 버전을 만드는 것이 아니라 워크 플로를 작성하고 방금 완료/추가 한 부분을 테스트하려는 경우 워크 플로의 이전 버전과 부분적으로 완료된 부분에 대해서는 신경 쓰지 않습니다. 데이터베이스의 워크 플로

감사합니다.

답변

1

나는 또한 비슷한 문제에 직면했다. 매번 워크 플로우 설계가 바뀌어 DB의 모든 이전 워크 플로우 인스턴스가 오류를 던진다.

이 문제를 해결하기 위해 각 워크 플로 유형에 대한 추적 프로필을 만들었습니다. 워크 플로를 변경 한 경우 내 프로필 버전을 업데이트했습니다. 이것은 나를 위해 일했습니다. 여기에 샘플 코드가 있습니다 -

이 경우 워크 플로우 런타임에 추적 서비스를 추가해야합니다.

TrackingProfile profile = CreateProfile();

StoreProfileToDB (프로필, connString, typeof (ExceptionWF.ParameterExceptionWF), "2.0.0.0");

개인 정적 TrackingProfile CreateProfile() { TrackingProfile myProfile = new TrackingProfile();

 ActivityTrackingLocation stateActivityLocation = CreateActivityLocation(typeof(StateActivity)); 
     AddActivityExecutionStatus(stateActivityLocation); 

     ActivityTrackingLocation eventDrivenActLoc = CreateActivityLocation(typeof(EventDrivenActivity)); 
     AddActivityExecutionStatus(eventDrivenActLoc); 

     ActivityTrackPoint actPt = new ActivityTrackPoint(); 

     actPt.MatchingLocations.Add(stateActivityLocation); 
     actPt.MatchingLocations.Add(eventDrivenActLoc); 
     myProfile.ActivityTrackPoints.Add(actPt); 

     WorkflowTrackPoint workflowTrack = CreateWorkflowTrackPoint(); 
     myProfile.WorkflowTrackPoints.Add(workflowTrack); 

     UserTrackPoint utp = new UserTrackPoint(); 
     UserTrackingLocation ul = new UserTrackingLocation(); 
     ul.ActivityType = typeof(HandleExternalEventActivity); 
     ul.ArgumentType = typeof(object); 
     ul.MatchDerivedArgumentTypes = true; 
     ul.MatchDerivedActivityTypes = true; 
     utp.MatchingLocations.Add(ul); 

     myProfile.UserTrackPoints.Add(utp); 
     myProfile.Version = new Version("1.0.0.0"); 
     return myProfile; 
    } 

    private static void StoreProfileToDB(TrackingProfile profile, string connString, Type wfType,string version) 
    { 
     TrackingProfileSerializer serializer = new TrackingProfileSerializer(); 
     System.IO.StringWriter writer = new System.IO.StringWriter(new StringBuilder()); 
     serializer.Serialize(writer, profile); 
     SqlConnection conn = null; 
     try 
     { 
      if (!String.IsNullOrEmpty(connString)) 
      { 
       conn = new SqlConnection(connString); 


       string storedProc = "dbo.UpdateTrackingProfile"; 
       SqlCommand cmd = new SqlCommand(storedProc, conn); 
       cmd.CommandType = System.Data.CommandType.StoredProcedure; 

       SqlParameter param = new SqlParameter("@TypeFullName", SqlDbType.NVarChar, 128); 
       param.Direction = ParameterDirection.Input; 
       param.Value = wfType.FullName; 
       cmd.Parameters.Add(param); 


       param = new SqlParameter("@AssemblyFullName", SqlDbType.NVarChar, 256); 
       param.Direction = ParameterDirection.Input; 
       param.Value = wfType.Assembly.FullName; 
       cmd.Parameters.Add(param); 


       param = new SqlParameter("@Version", SqlDbType.VarChar, 32); 
       param.Direction = ParameterDirection.Input; 
       //Note that you should increment version number for your 
       //TrackingProfile to be able to use new TrackingProfile. 
       //Default version is "1.0.0.0, It uses the default profile if not increamented. 
       param.Value = version; 
       cmd.Parameters.Add(param); 

       param = new SqlParameter("@TrackingProfileXml", SqlDbType.NText); 
       param.Direction = ParameterDirection.Input; 
       param.Value = writer.ToString(); 
       cmd.Parameters.Add(param); 

       conn.Open(); 
       cmd.ExecuteNonQuery(); 

      }//if 
     }// try 
     catch (Exception ex) 
     { 
      if (ex is SqlException) 
      { 
       //Check to see if it's a version error 
       if (ex.Message.Substring(0, 24) == "A version already exists") 
       { 
        EventLogger.Log("A profile with the same version already exists in database"); 
       }//if 
       else 
       { 
        EventLogger.Log("Error writing profile to database : " + ex.ToString()); 
       } 
      } 
      else 
      { 
       EventLogger.Log("Error writing profile to database : " + ex.ToString()); 
      } 
     } 
     finally 
     { 
      if (conn != null) { conn.Close(); } 
     } 
    } 
+0

또한 프로필은 전역 어셈블리 캐시에 여러 워크 플로 버전을로드하는 옵션입니다. 좋은 소식은 이것이 .NET4.0에서는 문제가되지 않는다는 것입니다. 4의 나쁜 소식은 언젠가 내년에 나올 예정입니다. – ahsteele

+0

@ksa - 수동으로 버전 번호를 늘리시겠습니까? 즉, 다시 컴파일하기 전에 워크 플로를 변경하면 소스 코드의 버전 번호가 올라갑니다. 나는 데이터베이스에서 추적 프로필을 비교하여 방금 만든 프로필과 비교해 보았습니다. 프로필이 다르면 버전을 늘리 겠지만 데이터베이스 오류가 계속 발생했습니다. 해결. @ahsteele - 나는 이것을 시도했지만 다시 실패했습니다 ... 지난주에 많은 승리를 얻지 못했습니다! 다시 시도 할 것입니다. :-) –

+0

프로필 버전을 변경 한 후에 DB를 "업데이트"하시겠습니까? 그렇다면이 문제를 말하십시오. DB의 이전 워크 플로 인스턴스에는 이전 프로필 버전이 필요합니다. 워크 플로우 디자인을 변경하면 코드에서 프로파일 버전을 업데이트하면됩니다 (u가 설계 또는 워크 플로우 코드를 변경했기 때문에). 이제 Db는 동일한 워크 플로 유형의 버전을 프로파일 링해야합니다. 희망이 도움이됩니다. – ksa