Esempio n. 1
0
        /// <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);
                }
            }
        }