调用了错误的保存、删除重载方法

1. 背景说明:

K/3 Cloud 为保存、删除处理,各自封装了多个重载方法。

很多人因为对这些重载方法的用途不了解,随意调用了不适合的重载方法保存、删除数据,造成数据不完整等问题,后续修复起来非常困难。




2. 错误案例:

如下帖中反馈的问题:
http://club.kisdee.com/forum.php?mod=viewthread&tid=1024936
IDeleteService接口删除单据时未清除T_BF_INSTANCEENTRY  

此贴反馈,明明已经调用了K/3 Cloud封装的删除服务删除单据,却发现,相关的业务流程数据却没有被删除,导致随后再次下推,控制错误。

这个帖子,反馈的问题原因,就是因为删除服务有3个重载,伙伴使用了 错误 的删除服务。

此贴调用的删除服务,只传入了单据ORM模型,以及单据内码,系统只会基于ORM模型,删除其物理表格中的数据,不做相关性处理。

简单的说,这个服务,就相当于后台删除单据数据表中的记录,其他相关数据,没有删除,因此造成数据删除不完整。




3. 保存服务(ISaveService.Save)介绍


保存服务接口为Kingdee.BOS.Contracts.ISaveService,Save方法,定义了两个重载。

3.1 重载一: 参数中带单据元数据  BusinessInfo


Kingdee.BOS.Core.DynamicForm.IOperationResult Save(
         Kingdee.BOS.Context ctx
         Kingdee.BOS.Core.Metadata.BusinessInfo info
         Kingdee.BOS.Orm.DataEntity.DynamicObject[] dataObject
         [Kingdee.BOS.Orm.OperateOption option = null], 
         [string operationNumber = ""])


参数说明
ctx: 数据库上下文
info:单据元数据
dataObject : 待保存的单据数据包
option : 操作操作选项,可以通过这个对象,传入一些特殊的控制选项,如是否忽略警告信息等
operationNumber : 保存操作编码(只有在单据上挂了多个保存操作时,才需要传入)

返回值:
返回单据保存操作执行结果,如操作是否成功,失败原因等

用途
此方法,是基于单据元数据的,执行单据上定义的保存操作;
完成的功能包括:
1. 执行操作校验
2. 执行操作上挂的服务;
3. 触发操作插件;
4. 保存单据本身数据(此为基本功能);
5. 记录单据关联数据,执行对源单的反写;

此方法,适合于保存单据。

3.2 重载二 :参数中仅仅包括orm数据包

Kingdee.BOS.Orm.DataEntity.DynamicObject[] Save(
         Kingdee.BOS.Context ctx
         Kingdee.BOS.Orm.DataEntity.DynamicObject[] dataObject)

参数说明
ctx: 数据库上下文
Ids: 待保存的orm数据包

返回值:
保存成功的orm数据包

用途:
此方法,仅仅执行:
1. 自动为orm数据包,产生主键
2. 保存orm数据包中的数据,到orm模型对应的物理表格中

此方法,不能用于保存单据。
K/3 Cloud定义了很多与单据无关的ORM模型,如消息模型、日志模型、网控模型等,可以用此方法保存这些数据。




4. 删除服务(IDeleteService.Delete)介绍
删除服务接口为Kingdee.BOS.Contracts.IDeleteService,Delete方法,定义了三个重载。

4.1 重载一: 参数中带单据元数据  BusinessInfo


Kingdee.BOS.Core.DynamicForm.IOperationResult Delete(
         Kingdee.BOS.Context ctx
         Kingdee.BOS.Core.Metadata.BusinessInfo info
         object[] Ids
         [Kingdee.BOS.Orm.OperateOption option = null], 
         [string operationNumber = ""])



参数说明
ctx: 数据库上下文
info:单据元数据
Ids : 待删除的单据内码
option : 操作操作选项,可以通过这个对象,传入一些特殊的控制选项,如是否忽略警告信息等
operationNumber : 删除操作编码(只有在单据上挂了多个删除操作时,才需要传入)

返回值:
返回单据删除操作执行结果,如操作是否成功,失败原因等

用途
此方法,是基于单据元数据的,执行单据上定义的删除操作;
完成的功能包括:
1. 执行删除操作校验
2. 执行删除操作上挂的服务;
3. 触发删除操作插件;
4. 删除单据本身数据(此为基本功能);
5. 删除单据关联数据,撤销对源单的反写;

此方法,适合于删除单据。

4.2 重载二 :参数中带单据标识 FormId

Kingdee.BOS.Core.DynamicForm.IOperationResult Delete(
         Kingdee.BOS.Context ctx
         string formid
         object[] Ids
         [Kingdee.BOS.Orm.OperateOption option = null], 
         [string operationNumber = ""])

参数说明
formid : 单据标识,系统会根据单据标识,自动加载单据元数据;
其他参数同重载一;

返回值:
返回单据删除操作执行结果,如操作是否成功,失败原因等

用途:
此方法,系统会根据单据标识,加载单据元数据,然后基于单据元数据的,执行单据上定义的删除操作;
完成的功能同重载一完全相同,而且参数准备,比重载一更加简单,不需要自行加载单据元数据。

此方法,也适合删除单据。

4.3 重载三 :参数中仅仅包括ORM模型

void Delete(
         Kingdee.BOS.Context ctx
         object[] Ids
         Kingdee.BOS.Orm.Metadata.DataEntity.DynamicObjectType dynamicObjectType)


参数说明
ctx: 数据库上下文
Ids: 待删除数据内码
dynamicObjectType : ORM模型

返回值:


用途:
此方法,仅仅执行:
1. 删除orm模型对应物料表格中的数据,其他无关数据,不做任何处理

此方法,不能用于删除单据,适用于删除与单据无关的数据。
K/3 Cloud定义了很多与单据无关的ORM模型,如消息模型、日志模型、网控模型等,可以用此方法删除数据。



5. 小结
综上所述,本帖介绍的错误案例,应该选用带BusinessInfo参数的删除方法重载一。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个用C++开发的简单宠物信息管理系统的源代码: ``` #include <iostream> #include <fstream> #include <string> #include <vector> #include <algorithm> using namespace std; // 宠物类 class Pet { public: int id; // 编号 string name; // 名字 string gender; // 性别 int age; // 年龄 string color; // 颜色 string type; // 种类 string ownerName; // 客户姓名 string ownerPhone; // 客户手机号 // 构造函数 Pet(int id, string name, string gender, int age, string color, string type, string ownerName, string ownerPhone) { this->id = id; this->name = name; this->gender = gender; this->age = age; this->color = color; this->type = type; this->ownerName = ownerName; this->ownerPhone = ownerPhone; } }; // 用户类 class User { public: string name; // 姓名 string password; // 密码 // 构造函数 User(string name, string password) { this->name = name; this->password = password; } }; // 管理员类,继承自用户类 class Admin : public User { public: // 构造函数,调用基类构造函数 Admin(string name, string password) : User(name, password) {} // 宠物信息录入函数 void addPet(vector<Pet>& pets) { int id, age; string name, gender, color, type, ownerName, ownerPhone; cout << "请输入宠物编号:"; cin >> id; cout << "请输入宠物名字:"; cin >> name; cout << "请输入宠物性别:"; cin >> gender; cout << "请输入宠物年龄:"; cin >> age; cout << "请输入宠物颜色:"; cin >> color; cout << "请输入宠物种类:"; cin >> type; cout << "请输入客户姓名:"; cin >> ownerName; cout << "请输入客户手机号:"; cin >> ownerPhone; pets.push_back(Pet(id, name, gender, age, color, type, ownerName, ownerPhone)); savePets(pets); // 保存宠物信息到文件 cout << "宠物信息录入成功!" << endl; } // 宠物信息修改函数 void modifyPet(vector<Pet>& pets) { int id; cout << "请输入要修改的宠物编号:"; cin >> id; // 查找宠物 auto it = find_if(pets.begin(), pets.end(), [id](const Pet& pet) { return pet.id == id; }); if (it == pets.end()) { cout << "找不到该宠物!" << endl; return; } // 修改宠物信息 cout << "请输入宠物名字:"; cin >> it->name; cout << "请输入宠物性别:"; cin >> it->gender; cout << "请输入宠物年龄:"; cin >> it->age; cout << "请输入宠物颜色:"; cin >> it->color; cout << "请输入宠物种类:"; cin >> it->type; cout << "请输入客户姓名:"; cin >> it->ownerName; cout << "请输入客户手机号:"; cin >> it->ownerPhone; savePets(pets); // 保存宠物信息到文件 cout << "宠物信息修改成功!" << endl; } // 宠物信息浏览函数 void viewPets(vector<Pet>& pets) { if (pets.empty()) { cout << "暂无宠物信息!" << endl; return; } cout << "编号\t名字\t性别\t年龄\t颜色\t种类\t客户姓名\t客户手机号" << endl; for (const auto& pet : pets) { cout << pet.id << "\t" << pet.name << "\t" << pet.gender << "\t" << pet.age << "\t" << pet.color << "\t" << pet.type << "\t" << pet.ownerName << "\t" << pet.ownerPhone << endl; } } // 宠物信息删除函数 void deletePet(vector<Pet>& pets) { int id; cout << "请输入要删除的宠物编号:"; cin >> id; // 查找宠物 auto it = find_if(pets.begin(), pets.end(), [id](const Pet& pet) { return pet.id == id; }); if (it == pets.end()) { cout << "找不到该宠物!" << endl; return; } pets.erase(it); // 删除宠物 savePets(pets); // 保存宠物信息到文件 cout << "宠物信息删除成功!" << endl; } // 模糊查询函数 void searchPets(vector<Pet>& pets) { string keyword; cout << "请输入关键字:"; cin >> keyword; auto it = find_if(pets.begin(), pets.end(), [keyword](const Pet& pet) { return pet.name.find(keyword) != string::npos || pet.ownerName.find(keyword) != string::npos; }); if (it == pets.end()) { cout << "找不到符合条件的宠物!" << endl; return; } cout << "编号\t名字\t性别\t年龄\t颜色\t种类\t客户姓名\t客户手机号" << endl; for (; it != pets.end(); ++it) { if (it->name.find(keyword) != string::npos || it->ownerName.find(keyword) != string::npos) { cout << it->id << "\t" << it->name << "\t" << it->gender << "\t" << it->age << "\t" << it->color << "\t" << it->type << "\t" << it->ownerName << "\t" << it->ownerPhone << endl; } } } // 按编号大小排序函数 void sortPets(vector<Pet>& pets) { sort(pets.begin(), pets.end(), [](const Pet& a, const Pet& b) { return a.id < b.id; }); cout << "编号\t名字\t性别\t年龄\t颜色\t种类\t客户姓名\t客户手机号" << endl; for (const auto& pet : pets) { cout << pet.id << "\t" << pet.name << "\t" << pet.gender << "\t" << pet.age << "\t" << pet.color << "\t" << pet.type << "\t" << pet.ownerName << "\t" << pet.ownerPhone << endl; } } private: // 从文件中读取宠物信息 void loadPets(vector<Pet>& pets) { ifstream infile("pets.txt"); if (!infile.is_open()) { cout << "打开文件失败!" << endl; return; } int id, age; string name, gender, color, type, ownerName, ownerPhone; while (infile >> id >> name >> gender >> age >> color >> type >> ownerName >> ownerPhone) { pets.push_back(Pet(id, name, gender, age, color, type, ownerName, ownerPhone)); } infile.close(); } // 将宠物信息保存到文件 void savePets(const vector<Pet>& pets) { ofstream outfile("pets.txt"); if (!outfile.is_open()) { cout << "打开文件失败!" << endl; return; } for (const auto& pet : pets) { outfile << pet.id << " " << pet.name << " " << pet.gender << " " << pet.age << " " << pet.color << " " << pet.type << " " << pet.ownerName << " " << pet.ownerPhone << endl; } outfile.close(); } }; // 客户类,继承自用户类 class Customer : public User { public: // 构造函数,调用基类构造函数 Customer(string name, string password) : User(name, password) {} // 查询宠物信息函数 void viewMyPets(const vector<Pet>& pets) { string keyword; cout << "请输入您的姓名或手机号:"; cin >> keyword; auto it = find_if(pets.begin(), pets.end(), [this, keyword](const Pet& pet) { return pet.ownerName == name && pet.ownerPhone == keyword; }); if (it == pets.end()) { cout << "找不到您的宠物信息!" << endl; return; } cout << "编号\t名字\t性别\t年龄\t颜色\t种类" << endl; for (; it != pets.end(); ++it) { if (it->ownerName == name && it->ownerPhone == keyword) { cout << it->id << "\t" << it->name << "\t" << it->gender << "\t" << it->age << "\t" << it->color << "\t" << it->type << endl; } } } }; int main() { vector<Pet> pets; Admin admin("admin", "admin"); // 管理员账号 Customer customer("zhangsan", "123456"); // 客户账号 int choice; // 从文件中加载宠物信息 admin.loadPets(pets); // 用户登录 string name, password; cout << "请输入用户名:"; cin >> name; cout << "请输入密码:"; cin >> password; if (name == admin.name && password == admin.password) { // 管理员登录 while (true) { // 显示菜单 cout << "宠物信息管理系统菜单:" << endl; cout << "1. 宠物信息录入" << endl; cout << "2. 宠物信息修改" << endl; cout << "3. 宠物信息浏览" << endl; cout << "4. 宠物信息删除" << endl; cout << "5. 模糊查询" << endl; cout << "6. 按编号大小排序" << endl; cout << "7. 退出" << endl; cout << "请选择操作:"; cin >> choice; // 执行操作 switch (choice) { case 1: admin.addPet(pets); break; case 2: admin.modifyPet(pets); break; case 3: admin.viewPets(pets); break; case 4: admin.deletePet(pets); break; case 5: admin.searchPets(pets); break; case 6: admin.sortPets(pets); break; case 7: return 0; default: cout << "无效操作!" << endl; } } } else if (name == customer.name && password == customer.password) { // 客户登录 while (true) { // 显示菜单 cout << "宠物信息查询菜单:" << endl; cout << "1. 查看我的宠物信息" << endl; cout << "2. 退出" << endl; cout << "请选择操作:"; cin >> choice; // 执行操作 switch (choice) { case 1: customer.viewMyPets(pets); break; case 2: return 0; default: cout << "无效操作!" << endl; } } } else { cout << "用户名或密码错误!" << endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值