2015-06-18 92 views
6

場景:C#WPF實體框架6同步數據庫

我有兩個MySQL數據庫:

  1. 大主數據庫
  2. 小型客戶端數據庫

實施例的表:

大數據庫用戶:

文本的用戶名

  • INT ID
  • VARCHAR登錄
  • VARCHAR密碼
  • ...很多更多的領域

客戶數據庫用戶

  • INT ID
  • int唯一api_id (ID來自主)
  • VARCHAR登錄
  • VARCHAR密碼

問題: 我需要同步數據庫,但我不不知道如何以最好的方式做到這一點。我讀this question,但它已經很老了,不包括我的情況。 我通過REST API與主數據庫進行通信,不直接連接。

我的同步算法

  • 下載和反序列化從REST API的數據(例如/ API /用戶/)來ApiUser對象列表
 

    public class ApiUser { 
     int id; 
     string login; 
     string password; 
    } 

    public class User{ 
     int id; 
     int api_id; 
     string login; 
     string password; 
    } 

  • 遍歷列表Apiusers
    • 如果實體與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

除了刪除從數據庫中的用戶是有可能有一個標誌WHI如果用戶被刪除,ch可以被標記爲true,以便您的代碼不會再次重新創建用戶? – Sandesh

回答

1

我假設所有用戶的交互或自動事務只在master數據庫中完成(否則你需要某種合併複製,這不是微不足道的)。

至於刪除的實體,有幾個選項。無論如何,您的主數據庫必須將有關已刪除實體的信息傳播到客戶端數據庫。

1.每個實體保存信息,如果它被刪除。

在這種情況下,您可以使用軟刪除選項,通過重寫DbContext的OnModelCreating和SaveChanges方法(您可以在網上找到許多代碼示例)來輕鬆實現。 這個選項也有一些缺點 - 你可能有相當複雜的領域模型與實體之間的關係,所以當你刪除他們的父項時你必須照顧軟刪除子實體。如果您對master數據庫和客戶端數據庫有不同的前端應用程序,則必須升級所有這些應用程序以使新的軟刪除屬性(例如IsDeleted)付諸行動。但是,(軟)刪除實體的同步本身在這種情況下非常簡單,因爲它只需在客戶端更新一個附加屬性。

2.刪除實體的新表。

在這種情況下,您必須爲每個實體創建一個附加表並在刪除任何實體之前插入Id值。您必須重寫DbContext的SaveChanges以截取EntityState.Deleted狀態下的實體。


關於第一個問題,它取決於你想要提高的。如果你期望在表中有很多記錄,你應該考慮引入額外的字段來只更新那些在master數據庫中真正更新的記錄 - 你可以分別在int(實體版本),DateTime或者guid值之間進行選擇,具體取決於是最適合你的情況。

如果您想分開處理屬性更新的問題,您可以創建專用實體模型僅用於同步目的,將數據反序列化爲這些對象,然後使用AutoMapper來更新您的實體,例如:

UPDATE

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();