Workflow 如何避免每次更改Windows工作流时都重建数据库
我正在将Windows工作流构建到.Net Web应用程序中。我遇到的问题是,每次我在状态机中添加、删除或更改活动,然后重新编译和运行它时,它就不再与数据库中用于跟踪和持久化的内容匹配。它不会更新更改,也不会在数据库中创建新版本的工作流,而是会抛出一个错误。有时它是一个“索引越界”错误,有时它是“无法获取成员XXXXX” 为了让它工作,我必须删除数据库并重新构建它。我相信这是可行的,因为当工作流引擎在数据库中查找工作流时,它没有找到它,因此将其添加到数据库中。这在我所处的阶段是非常令人沮丧的,我正在构建工作流程,并且它在一天中会改变很多次 是否有一种方法可以让工作流引擎使用我对工作流所做的更改来更新数据库中的相关表?或者用新版本覆盖它?我看了很多关于在运行时设置动态更新工作流的网页,但是这些建议对我都不起作用。虽然这是我想要的工作流功能,但我不确定这是否真的是解决我遇到的问题的方法。与其说我正在创建一个新版本的工作流,不如说我正在构建一个工作流,并希望测试我刚刚完成/添加的部分,我不关心工作流的早期版本和数据库中任何部分完成的工作流Workflow 如何避免每次更改Windows工作流时都重建数据库,workflow,workflow-foundation,Workflow,Workflow Foundation,我正在将Windows工作流构建到.Net Web应用程序中。我遇到的问题是,每次我在状态机中添加、删除或更改活动,然后重新编译和运行它时,它就不再与数据库中用于跟踪和持久化的内容匹配。它不会更新更改,也不会在数据库中创建新版本的工作流,而是会抛出一个错误。有时它是一个“索引越界”错误,有时它是“无法获取成员XXXXX” 为了让它工作,我必须删除数据库并重新构建它。我相信这是可行的,因为当工作流引擎在数据库中查找工作流时,它没有找到它,因此将其添加到数据库中。这在我所处的阶段是非常令人沮丧的,我
谢谢。我也遇到了类似的问题,每次工作流设计被更改时,数据库中的所有旧工作流实例都会抛出错误 为了克服这个问题,我为每种类型的工作流创建了跟踪配置文件。如果我更改了任何工作流,我会更新配置文件的版本。这对我来说很有效..下面是示例代码- 为此,您需要将跟踪服务添加到工作流运行时 TrackingProfile=CreateProfile() StoreProfileToDB(配置文件、连接字符串、类型(wf.ParameterExceptionWF除外),“2.0.0.0”) 私有静态跟踪配置文件CreateProfile() { TrackingProfile myProfile=新TrackingProfile()
此外,配置文件跟踪的另一个选项是将多个工作流版本加载到全局程序集缓存中。好消息是,这在.NET4.0中不会成为问题。坏消息4将在明年某个时候发布。@ksa-您是否手动增加版本号?也就是说,如果您在重新启动com之前更改了工作流你在源代码中增加了版本号吗?我尝试过这样做,将我数据库中的跟踪配置文件与刚创建的跟踪配置文件进行比较,如果它们不同,我会更新配置文件并增加版本,但我不断遇到无法解决的db错误。@ahsteele-我也尝试过,但是再次失败…上周对我来说没有太多胜利!我将重试。:-)你的意思是说,在更改配置文件版本后,你“更新”数据库,如果是,那么这就是问题所在。数据库中的旧工作流实例仍然需要旧的配置文件版本。当你更改工作流设计时,只需在代码中更新配置文件的版本(因为您更改了设计或工作流程代码)。数据库现在应该必须分析相同工作流类型的版本。希望这能有所帮助。我回到这里是因为我的跟踪根本不起作用。我在代码示例中注意到,xml中的配置文件版本与数据库字段中存储的配置文件版本不同。这是有意的吗?我认为它们应该是相同的。
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(); }
}
}