面试题答案
一键面试1. 存储事件
- 定义事件类:
- 为订单系统定义不同类型的事件类,例如订单创建事件、订单状态更新事件、订单支付事件等。每个事件类继承自一个基事件类,基事件类可包含公共属性,如事件发生时间、事件唯一标识等。
public abstract class BaseEvent { public Guid EventId { get; set; } public DateTime OccurredOn { get; set; } public BaseEvent() { EventId = Guid.NewGuid(); OccurredOn = DateTime.Now; } } public class OrderCreatedEvent : BaseEvent { public string OrderId { get; set; } public string CustomerId { get; set; } // 订单创建时的其他信息 } public class OrderStatusUpdatedEvent : BaseEvent { public string OrderId { get; set; } public string NewStatus { get; set; } }
- 选择事件存储方式:
- 文件存储:可将事件序列化为JSON或XML格式,然后写入文件。例如使用
System.IO
命名空间下的类。
using System.IO; using System.Text.Json; public class FileEventStore { private readonly string _filePath; public FileEventStore(string filePath) { _filePath = filePath; } public void StoreEvent(BaseEvent @event) { var json = JsonSerializer.Serialize(@event); File.AppendAllText(_filePath, json + Environment.NewLine); } }
- 数据库存储:使用关系型数据库(如SQL Server、MySQL)或非关系型数据库(如MongoDB)。以SQL Server为例,创建一个表用于存储事件,表结构包含事件ID、事件类型、事件数据(序列化后存储)、发生时间等字段。
using System.Data.SqlClient; using System.Text.Json; public class SqlEventStore { private readonly string _connectionString; public SqlEventStore(string connectionString) { _connectionString = connectionString; } public void StoreEvent(BaseEvent @event) { var json = JsonSerializer.Serialize(@event); var eventType = @event.GetType().Name; using (var connection = new SqlConnection(_connectionString)) { connection.Open(); var command = new SqlCommand("INSERT INTO Events (EventId, EventType, EventData, OccurredOn) VALUES (@EventId, @EventType, @EventData, @OccurredOn)", connection); command.Parameters.AddWithValue("@EventId", @event.EventId); command.Parameters.AddWithValue("@EventType", eventType); command.Parameters.AddWithValue("@EventData", json); command.Parameters.AddWithValue("@OccurredOn", @event.OccurredOn); command.ExecuteNonQuery(); } } }
- 文件存储:可将事件序列化为JSON或XML格式,然后写入文件。例如使用
2. 重建状态
- 定义订单状态类:
- 包含订单的各种状态属性,如订单ID、客户ID、订单状态、创建时间等。
public class OrderStatus { public string OrderId { get; set; } public string CustomerId { get; set; } public string Status { get; set; } public DateTime CreatedOn { get; set; } }
- 状态重建逻辑:
- 从事件存储中读取所有与特定订单相关的事件。根据事件的发生顺序依次应用事件来重建订单状态。
public class OrderStatusReconstructor { private readonly IEventStore _eventStore; public OrderStatusReconstructor(IEventStore eventStore) { _eventStore = eventStore; } public OrderStatus ReconstructStatus(string orderId) { var events = _eventStore.GetEventsByOrderId(orderId); var status = new OrderStatus(); foreach (var @event in events) { if (@event is OrderCreatedEvent createdEvent) { status.OrderId = createdEvent.OrderId; status.CustomerId = createdEvent.CustomerId; status.CreatedOn = createdEvent.OccurredOn; status.Status = "Created"; } else if (@event is OrderStatusUpdatedEvent updatedEvent) { status.Status = updatedEvent.NewStatus; } } return status; } }
3. 在电商订单系统中的应用
- 订单创建:
- 当创建订单时,生成
OrderCreatedEvent
并存储到事件存储中。
var orderCreatedEvent = new OrderCreatedEvent { OrderId = "12345", CustomerId = "67890" }; var eventStore = new FileEventStore("orders.events"); eventStore.StoreEvent(orderCreatedEvent);
- 当创建订单时,生成
- 订单状态更新:
- 当订单状态发生变化时,生成
OrderStatusUpdatedEvent
并存储。
var orderStatusUpdatedEvent = new OrderStatusUpdatedEvent { OrderId = "12345", NewStatus = "Shipped" }; eventStore.StoreEvent(orderStatusUpdatedEvent);
- 当订单状态发生变化时,生成
- 追踪订单状态:
- 通过
OrderStatusReconstructor
重建订单状态,以追踪订单的当前状态。
var reconstructor = new OrderStatusReconstructor(eventStore); var orderStatus = reconstructor.ReconstructStatus("12345"); Console.WriteLine($"Order {orderStatus.OrderId} is in {orderStatus.Status} status.");
- 通过
4. 其他考虑
- 版本控制:随着业务发展,事件类可能需要修改。可通过在事件类中添加版本号字段,在应用事件时根据版本号进行相应处理。
- 事件验证:在存储事件前,对事件数据进行验证,确保数据的准确性和完整性。
- 性能优化:对于大量事件的存储和读取,需要考虑性能优化,如使用缓存、优化数据库查询等。