想象一下WebForms应用程序,其中有一个名为CreateAll()的主方法.我可以一步一步地描述方法任务的过程如下:
1)存储到数据库(更新/创建Db项目3-4次)
2)启动一个新线程
3)Result1 =调用soap服务,并使用超时阈值检查状态和x分钟后.它继续(状态现在正常,这并不意味着失败)
4)存储到数据库(更新/创建Db项目3-4次)
5)result2 =呼叫肥皂服务(以火灾和忘记的方式)
6)更新配置文件(实际上从result1获取)
7)通过使用回调请求,它检查前端的每x秒结果2的状态,UI显示进度条.如果过程结束(100%)则表示成功
我正在考虑所有这些都是可以按类型分组的任务.基本上,几种类型的操作是:
我想为现有实现添加回滚/重试机制,并使用面向任务的体系结构并重构现有的遗留代码.
我发现C#中的Memento Design Pattern或Command Pattern之类的东西可以帮助达到这个目的.我还发现msdn Retry Pattern描述很有趣.我真的不知道,我希望有人带领我做出最安全和最好的决定......
您是否可以建议我保留现有实现和流程的最佳方法,但将其包装在一般的抽象重试/回滚/任务列表实现中?
最终的实现必须能够在每种情况下重试(无论任何任务或一般故障,例如整个createAll流程中的超时等),并且还会有一个回滚决策列表,其中应用程序必须能够回滚已完成的所有任务.
我想要一些例子来打破这个耦合代码.
PseudoCode可能有用:
class something
{
static result CreateAll(object1 obj1, object2 obj2 ...)
{
//Save to database obj1
//...
//Update to database obj1
//
//NEW THREAD
//Start a new thread with obj1, obj2 ...CreateAll
//...
}
void CreateAllAsync()
{
//Type1 Save to database obj1
//...
//Type1 Update to database obj2
//Type2 Call …Run Code Online (Sandbox Code Playgroud) 有一个扩展的命令模式实现,以支持C#中的多命令(组):
var ctx= //the context object I am sharing...
var commandGroup1 = new MultiItemCommand(ctx, new List<ICommand>
{
new Command1(ctx),
new Command2(ctx)
});
var commandGroup2 = new MultiItemCommand(ctx, new List<ICommand>
{
new Command3(ctx),
new Command4(ctx)
});
var groups = new MultiCommand(new List<ICommand>
{
commandGroup1 ,
commandGroup2
}, null);
Run Code Online (Sandbox Code Playgroud)
现在,执行就像:
groups.Execute();
Run Code Online (Sandbox Code Playgroud)
我正在共享相同的上下文(ctx)对象.
Web应用程序的执行计划需要在不同的线程中分离
commandGroup1和commandGroup2分组.具体来说,commandGroup2将在新线程和commandGroup1主线程中执行.
执行现在看起来像:
//In Main Thread
commandGroup1.Execute();
//In the new Thread
commandGroup2.Execute();
Run Code Online (Sandbox Code Playgroud)
如何线程安全地共享相同的内容context object (ctx),以便能够 …
我在我的应用程序中实现了命令模式(以多种支持方式).
结构体:
class MultiCommand : BaseCommand
abstract class BaseCommand : ICommand
Run Code Online (Sandbox Code Playgroud)
流程:
var commandsGroup = new MultiCommand(new List<ICommand>()
{
new Command1(),
new Command2(),
new Command3(),
});
commandsGroup.Execute()
Run Code Online (Sandbox Code Playgroud)
现在,假设在Command1a中somethingID已更改并且我将在Command2...中使用此新值.并且还有许多其他属性和对象在整个执行过程中受到影响.
此外,还有一些接口实现应该可以在任何命令中使用,只需使用上下文对象,如:
Context.ServerController.something();
Run Code Online (Sandbox Code Playgroud)
IServerController将在multiCommandGroup初始化之前进行实例化.
如何为组中的所有命令创建这样的共享上下文?
Context类的示例:
public class CommandContext
{
public IServerController ServerController;
public RequiredData Data { get; set; }
public CommandContext(){}
}
Run Code Online (Sandbox Code Playgroud)
重要信息 最小的实施代码在这里
我使用命令模式和自定义重试机制创建了一个回滚/重试机制,其中RetryCount和timeout threshold属性作为输入(如此处所述, 这是在C#中为同步/异步任务添加重试/回滚机制的最佳方法?).我也尝试了Polly框架,它很棒!
现在,我想将它们包装在一个抽象中.我可以将其描述为命令计划机制或基于命令的决策机制.
因此,根据命令结果的不同组合,我必须决定哪些已完成的命令将被还原,哪些不是(我想提供按下ReTry按钮的功能,一些命令不应该被还原) .
这些命令按某些类别分组,我必须针对不同的组和命令采取不同的回滚策略(基于结果).这里会有一些不同的政策!
重要提示:我想避免IF/ELSE等等.也许责任链模式可以帮助我,但我不知道,我真的想要帮助:
//Pseudo-code...
CommandHandler actionManager1 = new Action1Manager();
CommandHandler actionManager2 = new Action2Manager();
CommandHandler actionManager2 = new Action3Manager();
actionManager1.SetNextObjManager(Action2Manager);
actionManager2.SetNextObjManager(Action3Manager);
actionManager1.ProcessAction(){...}
actionManager1.ProcessAction(){...}
...
Run Code Online (Sandbox Code Playgroud)
另一个想法可能是观察者或事件处理者,但问题是如何使用它们(?).或者只是使用命令的列表/堆栈/队列并检查该列表以采取下一步的决定(?):
private List<ICommand> rollbackCommandsOfAllGroups;
private List<ICommand> rollbackCommandsOfGroup1;
private List<ICommand> rollbackCommandsOfGroup2;
...
Run Code Online (Sandbox Code Playgroud)
情景
最后,您可以考虑分为四(4)个类别的二十(20)个命令.
场景1
决定1
情景2
我正在使用SQL Server.对于每一个:
select * from ServiceItems where Itemtypeid=7004 (query1)
Run Code Online (Sandbox Code Playgroud)
我想在同一个表中插入三个新行,如:
(ItemID, PackageID, ItemTypeID, ServiceID, ItemName, CreatedDate) VALUES
(19377, 5352, 7007, 2011, N'L1', '11/11/2015 6:50:51 PM'),
(19378, 5352, 7008, 2011, N'M1', '11/11/2015 6:50:51 PM'),
(19376, 5352, 7006, 2011, N'W1', '11/11/2015 6:50:51 PM')
ItemID = is the primary key
PackageID = one from query1
ItemTypeID = as it is 7006,7007,700
ServiceID = one from query1
ItemName = as it is L1,M1,W1
CreatedDate = time now
Run Code Online (Sandbox Code Playgroud)
我试过了 INSERT INTO SELECT...
INSERT INTO ServiceItems …Run Code Online (Sandbox Code Playgroud) 我试过这个C#代码:
//items is the list of objects that contain the property a (int) and b(int)
var listOfInts= items.Select(p => new {p.a, p.b}).Distinct().
OrderByDescending(p => p.a).ToList();
//the result is a list of a' wew {p.a, p.b} AND not a list of integers.
Run Code Online (Sandbox Code Playgroud)
我只想将所有对象的这两个属性添加到一个简单的整数列表中,即linq或lambda表达式.
提前致谢!