/// <summary> /// 增减外键引用计数值 /// </summary> internal async ValueTask AddEntityRefAsync(EntityRefModel entityRef, ApplicationModel fromApp, Entity fromEntity, int diff) { Debug.Assert(diff != 0); Debug.Assert(fromEntity.Id.RaftGroupId != 0); var targetId = fromEntity.GetEntityId(entityRef.FKMemberIds[0]); if (targetId == null || targetId.IsEmpty) { return; } ulong targetModelId = entityRef.IsAggregationRef ? fromEntity.GetUInt64(entityRef.TypeMemberId) : entityRef.RefModelIds[0]; var targetModel = await RuntimeContext.Current.GetModelAsync <EntityModel>(targetModelId); var targetAppId = IdUtil.GetAppIdFromModelId(targetModelId); var targetApp = await RuntimeContext.Current.GetApplicationModelAsync(targetAppId); //注意编码 uint fromTableId = KeyUtil.EncodeTableId(fromApp.StoreId, entityRef.Owner.TableId); var item = new RefFromItem() { TargetEntityId = targetId, FromTableId = fromTableId, FromRaftGroupId = fromEntity.Id.RaftGroupId }; lock (this) { if (refs == null) { item.Diff = diff; refs = new List <RefFromItem> { item }; } else { for (int i = 0; i < refs.Count; i++) { if (refs[i].TargetEntityId == targetId && refs[i].FromRaftGroupId == fromEntity.Id.RaftGroupId) { item.Diff = refs[i].Diff + diff; refs[i] = item; return; } } //未找到 item.Diff = diff; refs.Add(item); } } }
/// <summary> /// 根据模型类型及标识号获取相应的节点 /// </summary> internal ModelNode FindModelNode(ModelType modelType, ulong modelId) { var appId = IdUtil.GetAppIdFromModelId(modelId); var modelRootNode = FindModelRootNode(appId, modelType); if (modelRootNode == null) { return(null); } return(modelRootNode.FindModelNode(modelId)); }
/// <summary> /// 加载指定App的所有模型包,用于导出 /// </summary> /// <param name="appName">eg: erp</param> internal static async Task LoadToAppPackage(uint appId, string appName, Server.IAppPackage pkg) { var db = SqlStore.Default; var esc = db.NameEscaper; var appPrefix = $"{appName}."; using var conn = await db.OpenConnectionAsync(); using var cmd = db.MakeCommand(); cmd.Connection = conn; cmd.CommandText = $"Select meta,id,data From {esc}sys.Meta{esc} Where meta<{Meta_View_Router} And model<>10"; using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { // 根据不同类型判断是否属于当前App var metaType = reader.GetInt16(0); var id = reader.GetString(1); switch (metaType) { case Meta_Application: { if (uint.Parse(id) == appId) { var appModel = (ApplicationModel)DeserializeModel((byte[])reader.GetValue(2)); //TODO: use GetStream pkg.Application = appModel; } } break; case Meta_Model: { ulong modelId = ulong.Parse(id); if (IdUtil.GetAppIdFromModelId(modelId) == appId) { var model = (ModelBase)DeserializeModel((byte[])reader.GetValue(2)); //TODO:同上 model.AcceptChanges(); pkg.Models.Add(model); } } break; case Meta_Code: { ulong modelId = ulong.Parse(id); if (IdUtil.GetAppIdFromModelId(modelId) == appId) { pkg.SourceCodes.Add(modelId, (byte[])reader.GetValue(2)); } } break; case Meta_Folder: { var dotIndex = id.AsSpan().IndexOf('.'); uint folderAppId = uint.Parse(id.AsSpan(0, dotIndex)); if (folderAppId == appId) { var folder = (ModelFolder)DeserializeModel((byte[])reader.GetValue(2)); //TODO:同上 pkg.Folders.Add(folder); } } break; case Meta_Service_Assembly: { if (id.AsSpan().StartsWith(appPrefix)) { pkg.ServiceAssemblies.Add(id, (byte[])reader.GetValue(2)); } } break; case Meta_View_Assembly: { if (id.AsSpan().StartsWith(appPrefix)) { pkg.ViewAssemblies.Add(id, (byte[])reader.GetValue(2)); } } break; default: Log.Warn($"Load unknown meta type: {metaType}"); break; } } }
/// <summary> /// 执行查询并返回Entity[] /// </summary> /// <returns>返回值可能为null</returns> public async ValueTask <IList <Entity> > ToListAsync() { var app = await RuntimeContext.Current.GetApplicationModelAsync(IdUtil.GetAppIdFromModelId(modelId)); var model = await RuntimeContext.Current.GetModelAsync <EntityModel>(modelId); var indexModel = model.SysStoreOptions.Indexes.SingleOrDefault(t => t.IndexId == indexId); if (indexModel == null) { throw new Exception("Index not exists."); } if (indexModel.Global) { throw new NotImplementedException(); } //先判断是否需要快照读事务 //TODO:跨分区也需要 ReadonlyTransaction txn = rootIncluder == null ? null : new ReadonlyTransaction(); if (model.SysStoreOptions.HasPartitionKeys) { //分区表先根据PartionPredicate查询出相关分区,再依次扫描 ulong[] parts = await GetPartitions(app.StoreId, model); if (parts == null || parts.Length == 0) { return(null); } var list = new List <Entity>((int)(take <= 1000 ? take : 20)); uint skipped = 0; uint taken = 0; for (int i = 0; i < parts.Length; i++) { var partRes = await ExecLocalIndexScanAsync(indexModel, parts[i], skip - skipped, take - taken, true); if (partRes != null) { partRes.ForEachRow((kp, ks, vp, vs) => { list.Add(EntityStoreReader.ReadEntity(model, kp, ks, vp, vs)); }); skipped += partRes.Skipped; taken += (uint)partRes.Length; partRes.Dispose(); if (taken >= take) { break; } } } await LoadIncludesAsync(list, txn); return(list); } else { ulong groupId = await EntityStore.GetOrCreateGlobalTablePartition(app, indexModel.Owner, IntPtr.Zero); if (groupId == 0) { return(null); } var res = await ExecLocalIndexScanAsync(indexModel, groupId, skip, take, true); if (res == null || res.Length == 0) { return(null); } var list = new Entity[res.Length]; int rowIndex = 0; res.ForEachRow((kp, ks, vp, vs) => { list[rowIndex] = EntityStoreReader.ReadEntity(model, kp, ks, vp, vs); rowIndex++; }); res.Dispose(); await LoadIncludesAsync(list, txn); return(list); } }