/// <summary> /// 构建给定类型的命令。 /// </summary> /// <param name="type">命令类型</param> /// <param name="dataTuple">数据项集合对</param> /// <param name="id"> /// 命令标识。 /// <remarks> /// 命令标识在命令的整个生命周期内是不改变的。命令标识在服务端命令创生时生成之后无论命令处在什么状态它的标识都是不变的。 /// 借助数据库层来说明这个问题:命令从ReceivedMessage表移到ExecutedMessage表的时候主键是不变的。 /// </remarks> /// </param> protected MessageBase(MessageTypeKind type, Guid id, DataItemsTuple dataTuple) { if (type == MessageTypeKind.Invalid) { throw new AnycmdException("非法的命令类型"); } if (id == Guid.Empty) { throw new AnycmdException("命令Id不能为空Guid"); } if (dataTuple == null) { throw new ArgumentNullException("dataTuple"); } Version = ApiVersion.V1.ToName(); this.CommandType = type; this.Id = id; this.DataTuple = dataTuple; }
/// <summary> /// /// </summary> /// <param name="acDomain"></param> /// <param name="commandType"></param> /// <param name="record"></param> /// <returns></returns> internal static CommandRecord Create(IAcDomain acDomain, MessageTypeKind commandType, System.Data.IDataRecord record) { MessageType requestType; record.GetString(record.GetOrdinal("MessageType")).TryParse(out requestType); ClientType clientType; record.GetString(record.GetOrdinal("ClientType")).TryParse(out clientType); return(new CommandRecord(commandType, record.GetGuid(record.GetOrdinal("Id")), DataItemsTuple.Create( acDomain, record.GetNullableString("InfoId"), record.GetNullableString("InfoValue"), record.GetNullableString("QueryList"), record.GetString(record.GetOrdinal("InfoFormat")))) { Verb = new Verb(record.GetString(record.GetOrdinal("Verb"))), Ontology = record.GetString(record.GetOrdinal("Ontology")), LocalEntityId = record.GetNullableString("LocalEntityId"), CatalogCode = record.GetNullableString("CatalogCode"), ClientId = record.GetString(record.GetOrdinal("ClientId")), TimeStamp = record.GetDateTime(record.GetOrdinal("TimeStamp")), ReceivedOn = record.GetDateTime(record.GetOrdinal("ReceivedOn")), CreateOn = record.GetDateTime(record.GetOrdinal("CreateOn")), ClientType = clientType, MessageType = requestType, MessageId = record.GetString(record.GetOrdinal("MessageId")), Status = record.GetInt32(record.GetOrdinal("Status")), ReasonPhrase = record.GetNullableString(record.GetOrdinal("ReasonPhrase")), Description = record.GetNullableString(record.GetOrdinal("Description")), EventSubjectCode = record.GetNullableString(record.GetOrdinal("EventSubjectCode")), EventSourceType = record.GetNullableString(record.GetOrdinal("EventSourceType")), UserName = record.GetNullableString("UserName"), IsDumb = record.GetBoolean(record.GetOrdinal("IsDumb")), Version = record.GetString(record.GetOrdinal("Version")) }); }
/// <summary> /// 创建给定的节点的命令 /// </summary> /// <param name="request"></param> /// <param name="responseNode"></param> /// <returns></returns> public static AnyMessage Create(HecpRequest request, NodeDescriptor responseNode) { if (request == null) { throw new ArgumentNullException("request"); } if (responseNode == null) { throw new ArgumentNullException("responseNode"); } var acDomain = responseNode.AcDomain; var clientId = string.Empty; var credential = request.Credential; if (credential == null) { throw new InvalidOperationException(); } switch (credential.ClientType) { case ClientType.Undefined: break; case ClientType.Node: NodeDescriptor requester; if (acDomain.NodeHost.Nodes.TryGetNodeByPublicKey(credential.ClientId, out requester)) { clientId = requester.Id.ToString(); } break; case ClientType.App: break; case ClientType.Monitor: break; default: break; } var dataTuple = DataItemsTuple.Create( acDomain, request.InfoId, request.InfoValue, request.QueryList, acDomain.Config.InfoFormat); MessageType requestType; request.MessageType.TryParse(out requestType); return(new AnyMessage(MessageTypeKind.AnyCommand, Guid.NewGuid(), dataTuple, responseNode) { Version = request.Version, IsDumb = request.IsDumb, Ontology = request.Ontology, ReceivedOn = DateTime.Now, CreateOn = DateTime.Now, MessageId = request.MessageId, ClientId = clientId, Verb = request.Verb, MessageType = requestType, ClientType = credential.ClientType, TimeStamp = SystemTime.ParseUtcTicksToLocalTime(request.TimeStamp), ReasonPhrase = request.EventReasonPhrase, Status = request.EventStatus, UserName = request.Credential.UserName, EventSourceType = request.EventSourceType, EventSubjectCode = request.EventSubject, LocalEntityId = null, Description = null, CatalogCode = null, From = request.From, RelatesTo = request.RelatesTo, To = request.To, SessionId = request.SessionId }); }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="dataTuple">数据项集合对</param> /// <param name="id">信息标识</param> /// <param name = "responseNode"></param> private AnyMessage(MessageTypeKind type, Guid id, DataItemsTuple dataTuple, NodeDescriptor responseNode) : base(type, id, dataTuple) { this._responseNode = responseNode; }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="dataTuple"></param> /// <param name = "responseNode"></param> private AnyMessage(MessageTypeKind type, DataItemsTuple dataTuple, NodeDescriptor responseNode) : this(type, Guid.NewGuid(), dataTuple, responseNode) { }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="dataTuple">数据项集合对</param> /// <param name="id">信息标识</param> public MessageEntity(MessageTypeKind type, Guid id, DataItemsTuple dataTuple) : base(type, id, dataTuple) { }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="dataTuple">数据项集合对</param> /// <param name="id">信息标识</param> private CommandRecord(MessageTypeKind type, Guid id, DataItemsTuple dataTuple) : base(type, id, dataTuple) { }
/// <summary> /// 根据给定的接收成功的命令建造待分发命令 /// </summary> /// <param name="tuple">已成功接收的命令类型的命令描述对象</param> /// <exception cref="AnycmdException"> /// 当<seealso cref="ToNode"/>是自己时发生,不能建造分发向自己的命令消息 /// </exception> /// <returns>待分发命令集合,可能为null</returns> public MessageEntity Build(MessageTuple tuple) { if (tuple == null) { throw new ArgumentNullException("tuple"); } #region 演出 if (ToNode == ToNode.AcDomain.NodeHost.Nodes.ThisNode) { throw new AnycmdException("不能建造分发向自己的命令消息"); } if (tuple.Context.ClientAgent == ToNode) { throw new AnycmdException("不能基于来源节点的命令建造分发向来源节点的命令"); } var actionCode = tuple.Context.Command.Verb; if (actionCode == Verb.Create || actionCode == Verb.Update) { var infoValueCares = new List <DataItem>(); foreach (var item in tuple.Context.InfoTuplePair.ValueTuple) { if (item.Element != tuple.Context.Ontology.IdElement && !item.Element.IsRuntimeElement && ToNode.IsCareforElement(item.Element)) { infoValueCares.Add(new DataItem(item.Key, item.Value)); } } DataItem[] infoIdItems = null; if (tuple.Tuple == null || ToNode.GetInfoIdElements().Any(a => a != tuple.Context.Ontology.IdElement && a.Element.IsInfoIdItem && !tuple.Tuple.Any(b => a.Element.Code.Equals(b.Key, StringComparison.OrdinalIgnoreCase)))) { if (actionCode == Verb.Create) { var selectElements = new OrderedElementSet(); foreach (var item in ToNode.GetInfoIdElements()) { if (item.Element.IsInfoIdItem) { selectElements.Add(item); } } infoIdItems = tuple.Context.Ontology.EntityProvider.GetTopTwo(tuple.Context.Ontology, new InfoItem[] { InfoItem.Create(tuple.Context.Ontology.IdElement, tuple.Context.LocalEntityId) }, selectElements).SingleInfoTuple.Select(e => new DataItem(e.Key, e.Value)).ToArray(); } else { infoIdItems = tuple.Context.TowInfoTuple.SingleInfoTuple .Where(e => e.Element.Element.IsInfoIdItem) .Select(e => new DataItem(e.Key, e.Value)).ToArray(); } } else { infoIdItems = tuple.Tuple.Where(e => e.Element.Element.IsInfoIdItem && ToNode.IsInfoIdElement(e.Element)).ToArray(); } DataItemsTuple dataTuple = DataItemsTuple.Create( ToNode.AcDomain, infoIdItems, infoValueCares.ToArray(), tuple.Context.Command.DataTuple.QueryList, tuple.Context.Command.DataTuple.InfoFormat); if (infoValueCares.Count > 0) { return(new MessageEntity(MessageTypeKind.Distribute, Guid.NewGuid(), dataTuple) { ClientId = ToNode.Node.Id.ToString(), Verb = tuple.Context.Command.Verb, LocalEntityId = tuple.Context.LocalEntityId, CatalogCode = tuple.Context.CatalogCode, ReceivedOn = tuple.Context.Command.ReceivedOn, CreateOn = DateTime.Now, Ontology = tuple.Context.Command.Ontology, ClientType = tuple.Context.Command.ClientType, TimeStamp = tuple.Context.Command.TimeStamp, MessageType = tuple.Context.Command.MessageType, MessageId = tuple.Context.Command.MessageId, Status = tuple.Context.Result.Status, ReasonPhrase = tuple.Context.Result.ReasonPhrase, Description = tuple.Context.Result.Description, EventSourceType = tuple.Context.Command.EventSourceType, EventSubjectCode = tuple.Context.Command.EventSubjectCode, UserName = tuple.Context.Command.UserName, IsDumb = tuple.Context.Command.IsDumb, Version = tuple.Context.Command.Version }); } } else if (actionCode == Verb.Delete) { if (ToNode.IsCareForOntology(tuple.Context.Ontology)) { DataItem[] infoIdItems = tuple.Context.TowInfoTuple.SingleInfoTuple .Where(e => e.Element.Element.IsInfoIdItem) .Select(e => new DataItem(e.Key, e.Value)).ToArray(); DataItemsTuple dataTuple = DataItemsTuple.Create(ToNode.AcDomain, infoIdItems, null, tuple.Context.Command.DataTuple.QueryList, tuple.Context.Command.DataTuple.InfoFormat); return(new MessageEntity(MessageTypeKind.Distribute, Guid.NewGuid(), dataTuple) { ClientId = ToNode.Node.Id.ToString(), Verb = tuple.Context.Command.Verb, LocalEntityId = tuple.Context.LocalEntityId, CatalogCode = tuple.Context.CatalogCode, ReceivedOn = tuple.Context.Command.ReceivedOn, CreateOn = DateTime.Now, Ontology = tuple.Context.Command.Ontology, ClientType = tuple.Context.Command.ClientType, TimeStamp = tuple.Context.Command.TimeStamp, MessageType = tuple.Context.Command.MessageType, MessageId = tuple.Context.Command.MessageId, Status = tuple.Context.Result.Status, ReasonPhrase = tuple.Context.Result.ReasonPhrase, Description = tuple.Context.Result.Description, EventSubjectCode = tuple.Context.Command.EventSubjectCode, EventSourceType = tuple.Context.Command.EventSourceType, UserName = tuple.Context.Command.UserName, IsDumb = tuple.Context.Command.IsDumb, Version = tuple.Context.Command.Version }); } } #endregion return(null); }
public override void Handle(AddBatchCommand command) { var batchRepository = _acDomain.RetrieveRequiredService<IRepository<Batch>>(); OntologyDescriptor ontology; if (!_acDomain.NodeHost.Ontologies.TryGetOntology(command.Input.OntologyId, out ontology)) { throw new ValidationException("非法的本体标识" + command.Input.OntologyId); } BatchType type; if (!command.Input.Type.TryParse(out type)) { throw new ValidationException("意外的批类型" + command.Input.Type); } var entity = Batch.Create(command.Input); var descriptor = new BatchDescriptor(_acDomain, entity); const int pageSize = 1000; const int pageIndex = 0; bool includeDescendants = entity.IncludeDescendants.HasValue && entity.IncludeDescendants.Value; NodeDescriptor toNode = null; if (!_acDomain.NodeHost.Nodes.TryGetNodeById(entity.NodeId.ToString(), out toNode)) { throw new AnycmdException("意外的节点标识" + entity.NodeId); } string thisNodeId = _acDomain.NodeHost.Nodes.ThisNode.Node.Id.ToString(); Verb actionCode; switch (descriptor.Type) { case BatchType.BuildCreateCommand: actionCode = Verb.Create; break; case BatchType.BuildUpdateCommand: actionCode = Verb.Update; break; case BatchType.BuildDeleteCommand: actionCode = Verb.Delete; break; default: throw new AnycmdException("意外的批类型" + entity.Type); } var commandFactory = _acDomain.NodeHost.MessageProducer; bool goOn = true; int count = 0; var pagingData = new PagingInput(pageIndex, pageSize, ontology.IncrementIdElement.Element.Code, "asc"); var selectElements = new OrderedElementSet {ontology.IdElement}; foreach (var item in ontology.Elements.Values.Where(a => a.Element.IsEnabled == 1)) { if (toNode.IsCareforElement(item) || toNode.IsInfoIdElement(item)) { selectElements.Add(item); } } var filters = new List<FilterData>(); if (ontology.Ontology.IsCataloguedEntity && !string.IsNullOrEmpty(entity.CatalogCode)) { filters.Add(includeDescendants ? FilterData.Like("ZZJGM", entity.CatalogCode + "%") : FilterData.EQ("ZZJGM", entity.CatalogCode)); } do { IDataTuples entities = ontology.EntityProvider.GetPlist(ontology, selectElements, filters, pagingData); if (entities != null && entities.Columns != null) { int idIndex = -1; for (int i = 0; i < entities.Columns.Count; i++) { if (entities.Columns[i] == ontology.IdElement) { idIndex = i; break; } } if (entities.Columns.Count == 0) { throw new AnycmdException("意外的查询列数"); } if (idIndex == -1) { throw new AnycmdException("未查询得到实体标识列"); } var products = new List<MessageEntity>(); foreach (var item in entities.Tuples) { var idItems = new InfoItem[] { InfoItem.Create(ontology.IdElement, item[idIndex].ToString()) }; var valueItems = new InfoItem[entities.Columns.Count - 1]; for (int i = 0; i < entities.Columns.Count; i++) { if (i < idIndex) { valueItems[i] = InfoItem.Create(entities.Columns[i], item[i].ToString()); } else if (i > idIndex) { valueItems[i - 1] = InfoItem.Create(entities.Columns[i], item[i].ToString()); } } var commandContext = new MessageContext(_acDomain, new MessageRecord( MessageTypeKind.Received, Guid.NewGuid(), DataItemsTuple.Create(_acDomain, idItems, valueItems, null, "json")) { Verb = actionCode, ClientId = thisNodeId, ClientType = ClientType.Node, TimeStamp = DateTime.Now, CreateOn = DateTime.Now, Description = entity.Type, LocalEntityId = item[idIndex].ToString(), Ontology = ontology.Ontology.Code, CatalogCode = null,// 如果按照目录分片分发命令的话则目录为空的分发命令是由专门的分发器分发的 MessageId = Guid.NewGuid().ToString(), MessageType = MessageType.Action, ReasonPhrase = "Ok", Status = 200, EventSourceType = string.Empty, EventSubjectCode = string.Empty, UserName = command.AcSession.Account.Id.ToString(), IsDumb = false, ReceivedOn = DateTime.Now, Version = ApiVersion.V1.ToName() }); products.AddRange(commandFactory.Produce(new MessageTuple(commandContext, valueItems), toNode)); } ontology.MessageProvider.SaveCommands(ontology, products.ToArray()); count = count + products.Count; pagingData.PageIndex++;// 注意这里不要引入bug。 } if (entities == null || entities.Tuples.Length == 0) { goOn = false; } } while (goOn); entity.Total = count; batchRepository.Add(entity); batchRepository.Context.Commit(); _acDomain.PublishEvent(new BatchAddedEvent(command.AcSession, entity)); _acDomain.CommitEventBus(); }