C# WPF 实体框架 6 同步数据库
本文关键字:同步 数据库 框架 WPF 实体 | 更新日期: 2023-09-27 17:56:47
>场景:
我有两个MySQL数据库:
- 大主数据库
- 小型客户端数据库
示例表:
大数据库用户:
文本用户名
- 整数标识
- 瓦尔查尔登录
- 瓦尔查尔密码
- 。更多字段
客户端数据库用户
- 整数标识
- int 唯一api_id(来自主节点的 ID)
- 瓦尔查尔登录
- 瓦尔查尔密码
问题:我需要同步数据库,但我不知道如何以最佳方式执行此操作。我读了这个问题,但它很旧,没有涵盖我的情况。我通过 REST API 与主数据库通信,直接连接不是选项。
我的同步算法
- 将数据从 REST API 下载并反序列化(例如/api/users/)到 ApiUser 对象列表
公共类 ApiUser { 整数 ID; 字符串登录; 字符串密码; } 公共类用户{ 整数 ID; 国际api_id; 字符串登录; 字符串密码; }
- 迭代 API 用户列表
- 如果存在 ApiUser.id 实体,则覆盖所有字段
- 否则创建新实体
- 保存更改
我的代码:
public void syncUsers(ListApiUsers) { using (var db = new dbEntities()) { ApiUsers.ForEach(apiUser => { var dbUser = db.client .其中(c => c.api_id == apiUser.id) .SingleOrDefault(); if (dbUser == null) { var userObj = new user() { api_id = apiUser.id, login = apiUser.login, 密码 = apiUser.password }; db.client.Add(userObj); } 还 { dbUser.api_id = apiUser.id, dbUser.login = apiUser.login, dbUser.password = apiUser.password } }); .db。保存更改(); } }
问题:如何做得更好?我对从 master 数据库中删除实体有问题,我的算法没有涵盖这种情况。
我假设所有用户的交互或自动事务仅在 master 数据库中完成(否则您将需要某种合并复制,这并非易事)。
至于已删除的实体,有几个选项。在任何情况下,master 数据库都必须将有关已删除实体的信息传播到客户端数据库。
1.如果信息被删除,则每个实体都持有该信息。
在这种情况下,可以使用软删除选项,该选项可以通过重写 DbContext 的 OnModelCreate 和 SaveChanges 方法在 EF 中轻松实现(可以在网络上找到许多实现的代码示例)。此选项也有一些缺点 - 您可能具有相当复杂的域模型,其中包含实体之间的关系,因此在删除父实体时必须注意软删除子实体。如果主数据库和客户端数据库有不同的前端应用程序,则必须升级所有这些前端应用程序,才能将新的软删除属性(例如 IsDeleted)付诸行动。但是在这种情况下,(软)删除实体的同步本身非常简单,因为它只需要在客户端更新一个附加属性。
2. 已删除实体的新表。
在这种情况下,您必须为每个实体创建一个附加表并插入 Id 值,然后再删除任何实体。您必须覆盖 DbContext 的 SaveChanges 才能拦截处于 EntityState.Delete 状态的实体。
关于第一个问题,这取决于您要增强什么。如果您希望表中有许多记录,则应考虑引入其他字段以仅更新在 master 数据库中真正更新的记录 - 您可以分别在 int(实体版本)、DateTime 或 guid 值之间进行选择,具体取决于最适合您的情况。
如果要分离处理逐个属性更新的关注点,则可以仅出于同步目的创建特殊的实体模型,将数据反序列化为这些对象,然后使用AutoMapper更新对象,例如:
更新
dbUser = Mapper.Map<User>(apiUser);
db.Set<User>().Attach(dbUser);
db.Entry(dbUser).State = EntityState.Modified;
db.SaveChanges();
加
dbUser = Mapper.Map<User>(apiUser);
db.client.Add(dbUser)
db.SaveChanges();