/// <summary> /// Called when the sync ensure scopes are created /// </summary> public virtual async Task <(SyncContext, List <ScopeInfo>)> EnsureScopesAsync(SyncContext context, string scopeName, Guid?clientReferenceId = null) { try { if (string.IsNullOrEmpty(scopeName)) { throw SyncException.CreateArgumentException(SyncStage.ScopeSaved, "ScopeName"); } context.SyncStage = SyncStage.ScopeLoading; List <ScopeInfo> scopes = new List <ScopeInfo>(); // Open the connection using (var connection = this.CreateConnection()) { try { await connection.OpenAsync(); using (var transaction = connection.BeginTransaction()) { var scopeBuilder = this.GetScopeBuilder(); var scopeInfoBuilder = scopeBuilder.CreateScopeInfoBuilder(connection, transaction); var needToCreateScopeInfoTable = scopeInfoBuilder.NeedToCreateScopeInfoTable(); // create the scope info table if needed if (needToCreateScopeInfoTable) { scopeInfoBuilder.CreateScopeInfoTable(); } // not the first time we ensure scopes, so get scopes if (!needToCreateScopeInfoTable) { // get all scopes shared by all (identified by scopeName) var lstScopes = scopeInfoBuilder.GetAllScopes(scopeName); // try to get the scopes from database // could be two scopes if from server or a single scope if from client scopes = lstScopes.Where(s => (s.IsLocal == true || (clientReferenceId.HasValue && s.Id == clientReferenceId.Value))).ToList(); } // If no scope found, create it on the local provider if (scopes == null || scopes.Count <= 0) { scopes = new List <ScopeInfo>(); // create a new scope id for the current owner (could be server or client as well) var scope = new ScopeInfo(); scope.Id = Guid.NewGuid(); scope.Name = scopeName; scope.IsLocal = true; scope.IsNewScope = true; scope.LastSync = null; scope = scopeInfoBuilder.InsertOrUpdateScopeInfo(scope); scopes.Add(scope); } else { //check if we have alread a good last sync. if no, treat it as new scopes.ForEach(sc => sc.IsNewScope = sc.LastSync == null); } // if we are not on the server, we have to check that we only have one scope if (!clientReferenceId.HasValue && scopes.Count > 1) { throw SyncException.CreateNotSupportedException(SyncStage.ScopeSaved, "On Local provider, we should have only one scope info"); } // if we have a reference in args, we need to get this specific line from database // this happen only on the server side if (clientReferenceId.HasValue) { var refScope = scopes.FirstOrDefault(s => s.Id == clientReferenceId); if (refScope == null) { refScope = new ScopeInfo(); refScope.Id = clientReferenceId.Value; refScope.Name = scopeName; refScope.IsLocal = false; refScope.IsNewScope = true; refScope.LastSync = null; refScope = scopeInfoBuilder.InsertOrUpdateScopeInfo(refScope); scopes.Add(refScope); } else { refScope.IsNewScope = refScope.LastSync == null; } } transaction.Commit(); } } catch (DbException dbex) { throw SyncException.CreateDbException(context.SyncStage, dbex); } catch (Exception dbex) { throw SyncException.CreateUnknowException(context.SyncStage, dbex); } finally { if (connection.State != ConnectionState.Closed) { connection.Close(); } } } // Event progress this.TryRaiseProgressEvent( new ScopeEventArgs(this.ProviderTypeName, context.SyncStage, scopes.FirstOrDefault(s => s.IsLocal)), ScopeLoading); return(context, scopes); } catch (Exception ex) { if (ex is SyncException) { throw; } else { throw SyncException.CreateUnknowException(context.SyncStage, ex); } } }
/// <summary> /// Ensure configuration is correct on both server and client side /// </summary> public virtual async Task <(SyncContext, SyncConfiguration)> EnsureConfigurationAsync(SyncContext context, SyncConfiguration configuration = null) { try { context.SyncStage = SyncStage.ConfigurationApplying; // Get cache manager and try to get configuration from cache var cacheManager = this.CacheManager; var cacheConfiguration = GetCacheConfiguration(); // if we don't pass config object (configuration == null), we may be in proxy mode, so the config object is handled by a local configuration object. if (configuration == null && this.syncConfiguration == null) { throw SyncException.CreateArgumentException(SyncStage.ConfigurationApplied, "Configuration", "You try to set a provider with no configuration object"); } // the configuration has been set from the proxy server itself, use it. if (configuration == null && this.syncConfiguration != null) { configuration = this.syncConfiguration; } // Raise event before context.SyncStage = SyncStage.ConfigurationApplying; var beforeArgs2 = new ConfigurationApplyingEventArgs(this.ProviderTypeName, context.SyncStage); this.TryRaiseProgressEvent(beforeArgs2, this.ConfigurationApplying); bool overWriteConfiguration = beforeArgs2.OverwriteConfiguration; // if we have already a cache configuration, we can return, except if we should overwrite it if (cacheConfiguration != null && !overWriteConfiguration) { // Raise event after context.SyncStage = SyncStage.ConfigurationApplied; var afterArgs2 = new ConfigurationAppliedEventArgs(this.ProviderTypeName, context.SyncStage, cacheConfiguration); this.TryRaiseProgressEvent(afterArgs2, this.ConfigurationApplied); // if config has been changed by user, save it again this.SetCacheConfiguration(cacheConfiguration); return(context, cacheConfiguration); } // create local directory if (!String.IsNullOrEmpty(configuration.BatchDirectory) && !Directory.Exists(configuration.BatchDirectory)) { Directory.CreateDirectory(configuration.BatchDirectory); } // if we dont have already read the tables || we want to overwrite the current config if ((configuration.HasTables && !configuration.HasColumns)) { string[] tables = new string[configuration.Count]; for (int i = 0; i < configuration.Count; i++) { // just check if we have a schema var dmTable = configuration[i]; var tableName = String.IsNullOrEmpty(dmTable.Schema) ? dmTable.TableName : $"[{dmTable.Schema}].[{dmTable.TableName}]"; tables[i] = tableName; } await this.ReadConfigurationAsync(configuration); } // save to cache this.SetCacheConfiguration(configuration); context.SyncStage = SyncStage.ConfigurationApplied; var afterArgs = new ConfigurationAppliedEventArgs(this.ProviderTypeName, context.SyncStage, configuration); this.TryRaiseProgressEvent(afterArgs, this.ConfigurationApplied); // if config has been changed by user, save it again this.SetCacheConfiguration(configuration); return(context, configuration); } catch (Exception ex) { if (ex is SyncException) { throw; } else { throw SyncException.CreateUnknowException(context.SyncStage, ex); } } }