C# WPF Entity Framework 6 数据库同步

7

情景:

我有两个MySQL数据库:

  1. 大型主数据库
  2. 小型客户端数据库

示例表:

大型数据库用户:

文本用户名

  • int id
  • varchar login
  • varchar password
  • …更多字段

客户端数据库用户

  • int id
  • int UNIQUE api_id (来自主数据库的id)
  • varchar login
  • varchar password

问题: 我需要同步数据库,但是我不知道最好的方法。我阅读了这篇文章,但它相当旧,而且没有涵盖我的情况。我通过REST API与主数据库通信,直接连接不是一个选项。

我的同步算法

  • 下载并反序列化来自REST API(例如/api/users/)的数据到ApiUser对象列表中
    public class ApiUser {
      int id;
      string login;
      string password; 
    }
public class User{ int id; int api_id; string login; string password; }
  • 遍历ApiUser列表
    • 如果具有ApiUser.id的实体存在,则覆盖所有字段
    • 否则创建新实体
  • 保存更改

我的代码:

public void syncUsers(List <ApiUser> ApiUsers)
{ using (var db = new dbEntities()) { ApiUsers.ForEach(apiUser => { var dbUser = db.client .Where(c => c.api_id == apiUser.id) .SingleOrDefault();
if (dbUser == null) { var userObj = new user() { api_id = apiUser.id, login = apiUser.login, password = apiUser.password }; db.client.Add(userObj); } else { dbUser.api_id = apiUser.id, dbUser.login = apiUser.login, dbUser.password = apiUser.password }
});
db.SaveChanges(); } }

问题: 怎样才能做得更好?我在处理来自主数据库中已删除的实体时存在问题,我的算法没有涵盖这种情况。


1
在数据库中,是否可以设置一个标志而不是删除用户,如果一个用户被删除,则可以将其标记为真,以便您的代码不会再次创建该用户? - Sandesh
1个回答

1
我假设所有用户的交互或自动化事务仅在主数据库中完成(否则您需要某种合并复制,这不是微不足道的)。至于已删除的实体,有几个选项。无论如何,您的主数据库都必须向客户端数据库传播有关已删除实体的信息。
1. 每个实体都保存了它是否已删除的信息。在这种情况下,您可以使用软删除选项,在EF中通过覆盖DbContext的OnModelCreating和SaveChanges方法轻松实现(您可以在网络上找到许多实现代码示例)。这个选项也有一些缺点 - 您可能有相当复杂的领域模型,其中实体之间存在关系,因此在删除其父项时,您必须小心地处理软删除子实体。如果您为主数据库和客户端数据库使用不同的前端应用程序,则必须升级所有这些应用程序以采取新的软删除属性(例如IsDeleted)行动。但在这种情况下,已(软)删除实体的同步本身非常简单,因为它只需要在客户端更新一个附加属性。
2. 为已删除实体创建新表。
在这种情况下,您需要为每个实体创建一个额外的表,并在删除任何实体之前插入Id值。您需要覆盖DbContext的SaveChanges以拦截处于EntityState.Deleted状态的实体。
关于第一个问题,它取决于您想要增强什么。如果您希望在表中有许多记录,则应考虑引入附加字段,仅更新实际在主数据库上更新的那些记录 - 您可以根据情况选择int(实体版本)、DateTime或guid值之间进行选择。
如果您想要分离按属性逐个更新的关注点,您可以为同步目的创建特殊的实体模型,将数据反序列化为这些对象,然后使用 AutoMapper来更新您的实体,例如:
更新
dbUser = Mapper.Map<User>(apiUser);
db.Set<User>().Attach(dbUser);
db.Entry(dbUser).State = EntityState.Modified;
db.SaveChanges();

ADD
dbUser = Mapper.Map<User>(apiUser);
db.client.Add(dbUser)
db.SaveChanges();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接