每次对Windows工作流程进行更改时,如何避免重建数据库

时间:2009-07-17 00:58:21

标签: workflow workflow-foundation

我正在将Windows工作流构建到.Net webapp中。我遇到的问题是,每次在状态机中添加或删除或更改活动,然后重新编译并运行它时,它就不再匹配数据库中的跟踪和持久性。不是更新更改,也不是在数据库中创建新版本的工作流,而是抛出错误。有时它会出现“索引越界”错误,其他时候会出现“无法获取成员XXXXX。”

为了让它工作,我必须删除数据库并重新构建它。我相信这是有效的,因为当工作流引擎在数据库中查找工作流时,它找不到它,因此将其添加到数据库中。这在我所处的阶段非常令人沮丧,我正在构建工作流程,并且它在一天内变化很多次。

有没有办法让我可以简单地让工作流引擎使用我对工作流程所做的更改来更新数据库中的相关表格?或者用新版本覆盖它?我已经查看了各种关于在运行时设置动态更新工作流程的网页,但这些建议都不适用于我。虽然这是我想要的工作流程的功能,但我不确定它是否真的是解决我遇到的问题的方法。我正在创建一个新版本的工作流程,而不是我正在构建一个工作流程,并希望测试我刚刚完成/添加的部分,我不关心以前版本的工作流程和任何部分完成数据库中的工作流程。

感谢。

1 个答案:

答案 0 :(得分:1)

我也面临类似的问题,每次工作流设计都发生变化,数据库中的所有旧工作流实例都会抛出错误。

为了解决这个问题,我为每种类型的工作流程创建了跟踪配置文件。如果我更改了任何工作流程,我更新了我的个人资料的版本。这对我有用..这是示例代码 -

为此,您需要向工作流运行时添加跟踪服务。

TrackingProfile profile = CreateProfile();

StoreProfileToDB(profile,connString,typeof(ExceptionWF.ParameterExceptionWF),“2.0.0.0”);

private static 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(); }
        }
    }