方案:

我有两个MySQL数据库:

  • 大数据库
  • 小客户端数据库

  • 表格示例:

    大数据库用户:

    文字使用者名称
  • int ID
  • varchar登录
  • varchar密码
  • ...更多字段

  • 客户端数据库用户
  • int ID
  • int唯一api_id(来自主服务器的ID)
  • varchar登录
  • varchar密码

  • 问题:
    我需要同步数据库,但是我不知道如何以最佳方式做到这一点。我读过this question,但是它已经很老了,不能涵盖我的情况。
    我通过REST API与主数据库进行通信,因此不能选择直接连接。

    我的同步算法
  • 将数据从REST API(例如/api/users/)下载并反序列化到ApiUser对象列表

  • 公共(public)类ApiUser {
    int id;
    字符串登录;
    字符串密码;
    }

    公共(public)类用户{
    int id;
    int api_id;
    字符串登录;
    字符串密码;
    }

  • 遍历Apiusers列表
  • 如果存在带有ApiUser.id的实体,则覆盖所有字段
  • 其他创建新实体
  • 保存更改

  • 我的代码:

    公共(public)无效syncUsers(列表 ApiUsers)

    {
    使用(var db = new dbEntities())
    {
    ApiUsers.ForEach(apiUser =>
    {
    var dbUser = db.client
    哪里(c => c.api_id == apiUser.id)
    .SingleOrDefault();

    如果(dbUser == null)
    {
    var userObj =新的user()
    {
    api_id = apiUser.id,
    登录= apiUser.login,
    密码= apiUser.password
    };
    db.client.Add(userObj);
    }
    别的
    {
    dbUser.api_id = apiUser.id,
    dbUser.login = apiUser.login,
    dbUser.password = apiUser.password
    }

    });

    db.SaveChanges();
    }
    }

    问题:
    如何做得更好?我在从主数据库中删除实体时遇到问题,我的算法没有涵盖这种情况。

    最佳答案

    我假设所有用户的交互或自动事务都仅在master数据库中完成(否则,您将需要某种合并复制,这并非易事)。

    至于已删除的实体,有几个选项。无论如何,您的主数据库必须将有关已删除实体的信息传播到客户端数据库。

    1.每个实体(如果已删除)都保留该信息。

    在这种情况下,您可以使用软删除选项,该选项可以通过覆盖DbContext的OnModelCreating和SaveChanges方法在EF中轻松实现(您可以在网上找到很多代码示例,其中包含实现)。
    此选项也有一些缺点-您可能拥有一个非常复杂的域模型,其中包含实体之间的关系,因此在删除其父实体时,必须小心地软删除子实体。如果您对主数据库和客户端数据库有不同的前端应用程序,则必须将它们全部升级,以使新的软删除属性(例如IsDeleted)生效。但是,在这种情况下,(软)已删除实体的同步本身非常简单,因为它只需要在客户端更新一个附加属性。

    2.删除实体的新表。

    在这种情况下,您必须为每个实体创建一个附加表,并在删除任何实体之前插入ID值。您必须重写DbContext的SaveChanges才能拦截处于EntityState.Deleted状态的实体。

    关于第一个问题,这取决于您要增强的功能。如果您希望表中有许多记录,则应考虑引入其他字段以仅更新那些在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();
    

    10-04 21:18
    查看更多