Files
sryang 577060bc78 chore: 首次簽入 Thinkyu ASP.NET 專案
- 加入 Visual Studio / ASP.NET .gitignore
- 排除建置輸出、IDE 設定、NuGet packages、大型 MSI 安裝檔
2026-09-10 09:42:37 +08:00

346 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using 報到系統客戶端.Data.Models;
using 報到系統客戶端.Data.Repositories;
using 報到系統客戶端.Models;
using 報到系統客戶端.Services;
namespace 報到系統客戶端.Data.Services
{
/// <summary>
/// 資料同步服務
/// 協調後端 API 和本地 SQLite 資料庫的資料同步
/// </summary>
public class DataSyncService
{
private readonly ClassesRepository _classesRepo;
private readonly SignUpsRepository _signUpsRepo;
public DataSyncService()
{
_classesRepo = new ClassesRepository();
_signUpsRepo = new SignUpsRepository();
}
/// <summary>
/// 同步 Classes 資料(從 API 到本地)
/// </summary>
public async Task<bool> SyncClassesFromApiAsync()
{
try
{
// 從 API 查詢資料
var response = await ClassesService.SearchClassesAsync();
if (!response.Success)
return false;
// 轉換資料
dynamic dataObj = response.Data;
if (dataObj == null)
return false;
_classesRepo.DeleteAll();
// 插入資料
foreach (var item in dataObj)
{
try
{
// 轉換為本地模型
var apiModel = (ClassesItem)item;
var localItem = LocalClassesItem.ConvertFromApiModel(apiModel);
// 檢查是否已存在
var existing = _classesRepo.GetById(localItem.ID);
if (existing != null)
{
_classesRepo.Update(localItem);
}
else
{
_classesRepo.Insert(localItem);
}
}
catch
{
// 忽略單筆資料錯誤,繼續同步其他資料
}
}
return true;
}
catch (Exception ex)
{
throw new Exception($"同步 Classes 資料失敗:{ex.Message}", ex);
}
}
/// <summary>
/// 同步 Classes 資料(同步版本)
/// </summary>
public bool SyncClassesFromApi()
{
try
{
// 從 API 查詢資料
var response = ClassesService.SearchClasses();
if (!response.Success)
return false;
// 轉換資料
dynamic dataObj = response.Data;
if (dataObj == null)
return false;
_classesRepo.DeleteAll();
// 插入資料
foreach (var item in dataObj)
{
try
{
// 轉換為本地模型
var apiModel = (ClassesItem)item;
var localItem = LocalClassesItem.ConvertFromApiModel(apiModel);
// 檢查是否已存在
var existing = _classesRepo.GetById(localItem.ID);
if (existing != null)
{
_classesRepo.Update(localItem);
}
else
{
_classesRepo.Insert(localItem);
}
}
catch
{
// 忽略單筆資料錯誤,繼續同步其他資料
}
}
return true;
}
catch (Exception ex)
{
throw new Exception($"同步 Classes 資料失敗:{ex.Message}", ex);
}
}
/// <summary>
/// 同步 SignUps 資料(從 API 到本地)
/// </summary>
public async Task<bool> SyncSignUpsFromApiAsync(int courseID, int pageIndex, int pageSize)
{
try
{
// 從 API 查詢資料
var response = await SignUpService.SearchSignUpsAsync(pageIndex, pageSize, courseID);
if (!response.Success)
return false;
// 轉換資料
dynamic dataObj = response.Data;
if (dataObj == null)
return false;
// 如果第一頁,先清除該課程的本地資料
if (pageIndex == 1)
{
var existingList = _signUpsRepo.GetByCourseID(courseID);
foreach (var item in existingList)
{
_signUpsRepo.Delete(item.ID);
}
}
// 插入資料
foreach (var item in dataObj)
{
try
{
// 轉換為本地模型
var apiModel = (SignUpItem)item;
var localItem = LocalSignUpItem.ConvertFromApiModel(apiModel);
// 檢查是否已存在
var existing = _signUpsRepo.GetById(localItem.ID);
if (existing != null)
{
_signUpsRepo.Update(localItem);
}
else
{
_signUpsRepo.Insert(localItem);
}
}
catch
{
// 忽略單筆資料錯誤,繼續同步其他資料
}
}
return true;
}
catch (Exception ex)
{
throw new Exception($"同步 SignUps 資料失敗:{ex.Message}", ex);
}
}
/// <summary>
/// 同步 SignUps 資料(同步版本)
/// </summary>
public bool SyncSignUpsFromApi(int courseID, int pageIndex, int pageSize)
{
try
{
// 從 API 查詢資料
var response = SignUpService.SearchSignUps(pageIndex, pageSize, courseID);
if (!response.Success)
return false;
// 轉換資料
dynamic dataObj = response.Data;
if (dataObj == null)
return false;
// 如果第一頁,先清除該課程的本地資料
if (pageIndex == 1)
{
var existingList = _signUpsRepo.GetByCourseID(courseID);
foreach (var item in existingList)
{
_signUpsRepo.Delete(item.ID);
}
}
// 插入資料
foreach (var item in dataObj)
{
try
{
// 轉換為本地模型
var apiModel = (SignUpItem)item;
var localItem = LocalSignUpItem.ConvertFromApiModel(apiModel);
// 檢查是否已存在
var existing = _signUpsRepo.GetById(localItem.ID);
if (existing != null)
{
_signUpsRepo.Update(localItem);
}
else
{
_signUpsRepo.Insert(localItem);
}
}
catch
{
// 忽略單筆資料錯誤,繼續同步其他資料
}
}
return true;
}
catch (Exception ex)
{
throw new Exception($"同步 SignUps 資料失敗:{ex.Message}", ex);
}
}
/// <summary>
/// 上傳本地 SignUps 簽到簽退資料到 API
/// </summary>
public async Task<bool> UploadSignUpsToApiAsync(int courseID)
{
try
{
var localItems = _signUpsRepo.GetByCourseID(courseID);
if (localItems.Count == 0)
return true;
// 轉換為 API 模型
var apiItems = new List<SignUpItem>();
foreach (var item in localItems)
{
apiItems.Add(LocalSignUpItem.ConvertToApiModel(item));
}
// 上傳到 API
var response = await SignUpService.UploadSignUpsAsync(courseID, apiItems);
return response.Success;
}
catch (Exception ex)
{
throw new Exception($"上傳 SignUps 資料失敗:{ex.Message}", ex);
}
}
/// <summary>
/// 上傳本地 SignUps 簽到簽退資料到 API(同步版本)
/// </summary>
public bool UploadSignUpsToApi(int courseID)
{
try
{
var localItems = _signUpsRepo.GetByCourseID(courseID);
if (localItems.Count == 0)
return true;
// 轉換為 API 模型
var apiItems = new List<SignUpItem>();
foreach (var item in localItems)
{
apiItems.Add(LocalSignUpItem.ConvertToApiModel(item));
}
// 上傳到 API
var response = SignUpService.UploadSignUps(courseID, apiItems);
return response.Success;
}
catch (Exception ex)
{
throw new Exception($"上傳 SignUps 資料失敗:{ex.Message}", ex);
}
}
/// <summary>
/// 清除所有本地資料
/// </summary>
public void ClearAllLocalData()
{
try
{
DatabaseService.Instance.ClearAllTables();
}
catch (Exception ex)
{
throw new Exception($"清除本地資料失敗:{ex.Message}", ex);
}
}
/// <summary>
/// 取得 Classes Repository
/// </summary>
public ClassesRepository GetClassesRepository()
{
return _classesRepo;
}
/// <summary>
/// 取得 SignUps Repository
/// </summary>
public SignUpsRepository GetSignUpsRepository()
{
return _signUpsRepo;
}
}
}