通过StateChangeEvent事件(StateChangeEventHadler委托)计算数据庫访问时间次数 

本文介绍了一个使用C#实现的示例程序,该程序演示了如何通过StateChange事件处理程序来监控SQL连接的状态变化,并在连接打开和关闭时记录相关信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


        通过委托计算数据庫访问时间,次数

每当客户打开,关闭連接时,为StateChange事件指定处理程序,
通过事件处理程序在列表框显示相关信息。
namespace @event
{
    
public partial class Form1 : Form
    
{
        
public Form1()
        
{
            InitializeComponent();
        }


     

        
private void cmdCnStateChange_Click(object sender, EventArgs e)
        
{
            SqlConnection cn
=
                
new SqlConnection(@"Data Source=localhost;Integrated Security=SSPI;database=Northwind");

            SqlCommand cmd
=new SqlCommand();
            cmd.CommandText
="SELECT CustomerId,CompanyName FROM Customers";
            cmd.Connection
=cn;
            cn.StateChange
+=new StateChangeEventHandler(CnStateChange);

            
try
            
{
             
                cn.Open();
                SqlDataReader dr 
= cmd.ExecuteReader();
            
                
while (dr.Read())
                
{
                    lbResult.Items.Add(dr.GetString(
0+ "-" + dr.GetString(1));
                   
                }

               
            }

            
catch (SqlException se)
            
{
                
foreach (SqlError err in se.Errors)
                
{
                    lbResult.Items.Add(err);
                }

            }

            
finally
            
{
                cn.Close();
            }

 

          }

        
private void CnStateChange(object sender, StateChangeEventArgs ev)
        
{
            lbResult.Items.Add(
"--------");
            lbResult.Items.Add(
"Entering StateChange EventHander");
            lbResult.Items.Add(
"Sender=" + sender.ToString());
            lbResult.Items.Add(
"Original State=" + System.DateTime.Now);//获取当前时间
            lbResult.Items.Add(
"Current State=" + ev.CurrentState.ToString());//获取当前状态
            lbResult.Items.Add(
"Exiting StateChange Event Hander");
            lbResult.Items.Add(
"--------");

        }

    

    }

}



<think>我们设计一个工单状态机,包含10种状态,并使用RabbitMQ来保证状态变更的最终一致性。 状态机设计要点: 1. 定义10种状态:例如:新建、已分配、处理中、待审核、已驳回、已解决、已关闭、重新打开、已取消、挂起等(具体根据业务需求)。 2. 状态流转规则:定义每个状态可以流转到哪些状态,例如“新建”可以流转到“已分配”或“已取消”。 3. 使用RabbitMQ:当工单状态发生变更时,将状态变更事件发布到RabbitMQ,然后由消费者异步处理状态更新,确保最终一致性。 实现步骤: a. 状态定义:枚举类(State)定义所有状态。 b. 状态流转规则:使用状态机配置(例如使用Spring StateMachine或自定义状态机规则)。 c. 状态变更事件:当工单状态变更时,将变更事件(包括工单ID、原状态、目标状态、变更时间等)发送到RabbitMQ。 d. 消费者:监听队列,接收到事件后更新数据库中的工单状态,并记录状态变更历史。 注意:为了确保最终一致性,在生产者端(状态变更请求)需要将事件可靠地发送到RabbitMQ,消费者端需要保证幂等性。 下面是一个简化的Java实现示例(使用Spring Boot, Spring StateMachine, RabbitMQ): 由于状态机配置复杂,这里只展示核心流程。</think>### 工单状态机实现(10种状态流转 + RabbitMQ最终一致性) #### 状态定义与流转规则(示例) ```mermaid stateDiagram-v2 [*] --> 新建 新建 --> 已分配: 分配资源 已分配 --> 处理中: 开始处理 处理中 --> 待审核: 提交审核 待审核 --> 已驳回: 审核不通过 待审核 --> 已解决: 审核通过 已驳回 --> 处理中: 重新处理 处理中 --> 挂起: 需要外部协助 挂起 --> 处理中: 问题解决 处理中 --> 已取消: 用户取消 已解决 --> 已关闭: 用户确认 已解决 --> 重新打开: 用户反馈 重新打开 --> 处理中: 重新分配 已关闭 --> [*] ``` #### Java实现(Spring Boot + RabbitMQ) ```java // 1. 状态枚举定义 public enum TicketState { NEW, // 新建 ASSIGNED, // 已分配 IN_PROGRESS, // 处理中 PENDING_REVIEW,// 待审核 REJECTED, // 已驳回 RESOLVED, // 已解决 CLOSED, // 已关闭 REOPENED, // 重新打开 CANCELLED, // 已取消 SUSPENDED // 挂起 } // 2. 状态转换服务(核心状态机) @Service @Transactional public class StateTransitionService { private static final Map<TicketState, Set<TicketState>> VALID_TRANSITIONS = Map.of( TicketState.NEW, Set.of(TicketState.ASSIGNED, TicketState.CANCELLED), TicketState.ASSIGNED, Set.of(TicketState.IN_PROGRESS, TicketState.CANCELLED), TicketState.IN_PROGRESS, Set.of(TicketState.PENDING_REVIEW, TicketState.SUSPENDED, TicketState.CANCELLED), TicketState.PENDING_REVIEW, Set.of(TicketState.REJECTED, TicketState.RESOLVED), TicketState.REJECTED, Set.of(TicketState.IN_PROGRESS), TicketState.RESOLVED, Set.of(TicketState.CLOSED, TicketState.REOPENED), TicketState.REOPENED, Set.of(TicketState.IN_PROGRESS), TicketState.SUSPENDED, Set.of(TicketState.IN_PROGRESS) ); @Autowired private TicketRepository ticketRepo; @Autowired private RabbitTemplate rabbitTemplate; // 状态变更请求 public void changeState(Long ticketId, TicketState newState) { Ticket ticket = ticketRepo.findById(ticketId) .orElseThrow(() -> new TicketNotFoundException(ticketId)); // 验证状态转换合法性 if (!VALID_TRANSITIONS.get(ticket.getState()).contains(newState)) { throw new InvalidStateTransitionException(ticket.getState(), newState); } // 发送状态变更事件到RabbitMQ(不立即更新DB) StateChangeEvent event = new StateChangeEvent(ticketId, ticket.getState(), newState); rabbitTemplate.convertAndSend("state-change-exchange", "state.change", event); } } // 3. RabbitMQ事件定义 public class StateChangeEvent implements Serializable { private Long ticketId; private TicketState fromState; private TicketState toState; private LocalDateTime timestamp = LocalDateTime.now(); // 构造方法/getters/setters } // 4. 状态变更消费者(保证最终一致性) @Component @RabbitListener(queues = "state-change-queue") public class StateChangeConsumer { @Autowired private TicketRepository ticketRepo; @RabbitHandler @Transactional public void handleEvent(StateChangeEvent event) { // 幂等性检查(通过事件ID或时间戳) if (isDuplicate(event)) return; Ticket ticket = ticketRepo.findById(event.getTicketId()) .orElseThrow(() -> new TicketNotFoundException(event.getTicketId())); // 二次验证状态转换(防止并发冲突) if (VALID_TRANSITIONS.get(ticket.getState()).contains(event.getToState())) { ticket.setState(event.getToState()); ticketRepo.save(ticket); logStateChange(ticket, event.getFromState()); } else { // 触发补偿机制(如发送告警) handleInvalidTransition(event); } } private void logStateChange(Ticket ticket, TicketState previousState) { // 记录状态变更历史(单独历史表) } } // 5. RabbitMQ配置 @Configuration public class RabbitConfig { @Bean public TopicExchange stateExchange() { return new TopicExchange("state-change-exchange"); } @Bean public Queue stateQueue() { return new Queue("state-change-queue", true); } @Bean public Binding stateBinding() { return BindingBuilder.bind(stateQueue()) .to(stateExchange()) .with("state.change"); } @Bean public Jackson2JsonMessageConverter jsonConverter() { return new Jackson2JsonMessageConverter(); } } ``` #### 最终一致性保障机制 1. **生产者端可靠性**: ```java // 添加发送确认回调 rabbitTemplate.setConfirmCallback((correlation, ack, reason) -> { if (!ack) { // 记录失败事件并重试 retryService.retrySend(event); } }); ``` 2. **消费者端幂等性**: ```java private boolean isDuplicate(StateChangeEvent event) { // 通过Redis SETNX检查事件ID String key = "event:" + event.getTicketId() + ":" + event.getToState(); return !redisTemplate.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.HOURS); } ``` 3. **死信处理**: ```java @Bean public Queue dlq() { return QueueBuilder.durable("state-change-dlq") .withArgument("x-dead-letter-exchange", "state-change-exchange") .withArgument("x-dead-letter-routing-key", "state.change.retry") .build(); } ``` #### 系统优势 1. **状态隔离**:前端请求与DB更新解耦 2. **最终一致性**:RabbitMQ保证事件至少投递一次 3. **可追溯性**:完整的状态变更历史记录 4. **弹性扩展**:可水平扩展消费者实例 5. **容错能力**:DLQ机制处理异常事件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值