Esempio n. 1
0
        /// <summary>
        /// Write scope in the provider datasource
        /// </summary>
        public virtual async Task <SyncContext> WriteScopesAsync(SyncContext context, List <ScopeInfo> scopes)
        {
            // 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 lstScopes = new List <ScopeInfo>();

                        foreach (var scope in scopes)
                        {
                            lstScopes.Add(scopeInfoBuilder.InsertOrUpdateScopeInfo(scope));
                        }

                        context.SyncStage = SyncStage.ScopeSaved;

                        // Event progress
                        this.TryRaiseProgressEvent(
                            new ScopeEventArgs(this.ProviderTypeName, context.SyncStage,
                                               lstScopes.FirstOrDefault(s => s.IsLocal)), ScopeSaved);

                        transaction.Commit();
                    }
                }
                catch (DbException dbex)
                {
                    throw SyncException.CreateDbException(context.SyncStage, dbex);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);

                    if (ex is SyncException)
                    {
                        throw;
                    }
                    else
                    {
                        throw SyncException.CreateUnknowException(context.SyncStage, ex);
                    }

                    throw;
                }
                finally
                {
                    if (connection.State != ConnectionState.Closed)
                    {
                        connection.Close();
                    }
                }
                return(context);
            }
        }
        /// <summary>
        /// Gets a batch of changes to synchronize when given batch size,
        /// destination knowledge, and change data retriever parameters.
        /// </summary>
        /// <returns>A DbSyncContext object that will be used to retrieve the modified data.</returns>
        public virtual async Task <(SyncContext, BatchInfo, ChangesSelected)> GetChangeBatchAsync(SyncContext context, ScopeInfo scopeInfo)
        {
            try
            {
                if (scopeInfo == null)
                {
                    throw new ArgumentException("ClientScope is null");
                }

                var configuration = GetCacheConfiguration();

                // check batchSize if not > then Configuration.DownloadBatchSizeInKB
                if (configuration.DownloadBatchSizeInKB > 0)
                {
                    Debug.WriteLine($"Enumeration data cache size selected: {configuration.DownloadBatchSizeInKB} Kb");
                }

                // bacth info containing changes
                BatchInfo batchInfo;

                // Statistics about changes that are selected
                ChangesSelected changesSelected;

                (context, batchInfo, changesSelected) = await this.GetChanges(context, scopeInfo);

                // Check if the remote is not outdated
                var isOutdated = this.IsRemoteOutdated();

                if (isOutdated)
                {
                    throw new Exception("OutDatedPeer");
                }

                return(context, batchInfo, changesSelected);
            }
            catch (DbException dbex)
            {
                throw SyncException.CreateDbException(context.SyncStage, dbex);
            }
            catch (Exception ex)
            {
                if (ex is SyncException)
                {
                    throw;
                }
                else
                {
                    throw SyncException.CreateUnknowException(context.SyncStage, ex);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Read a scope info
        /// </summary>
        public virtual async Task <(SyncContext, long)> GetLocalTimestampAsync(SyncContext context)
        {
            // Open the connection
            using (var connection = this.CreateConnection())
            {
                try
                {
                    await connection.OpenAsync();

                    var scopeBuilder     = this.GetScopeBuilder();
                    var scopeInfoBuilder = scopeBuilder.CreateScopeInfoBuilder(connection);
                    var localTime        = scopeInfoBuilder.GetLocalTimestamp();
                    return(context, localTime);
                }
                catch (DbException dbex)
                {
                    throw SyncException.CreateDbException(context.SyncStage, dbex);
                }
                catch (Exception ex)
                {
                    if (ex is SyncException)
                    {
                        throw;
                    }
                    else
                    {
                        throw SyncException.CreateUnknowException(context.SyncStage, ex);
                    }
                }
                finally
                {
                    if (connection.State != ConnectionState.Closed)
                    {
                        connection.Close();
                    }
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Be sure all tables are ready and configured for sync
        /// the ScopeSet Configuration MUST be filled by the schema form Database
        /// </summary>
        public virtual async Task <SyncContext> EnsureDatabaseAsync(SyncContext context, ScopeInfo scopeInfo)
        {
            var configuration = GetCacheConfiguration();

            // Event progress
            context.SyncStage = SyncStage.DatabaseApplying;
            DatabaseApplyingEventArgs beforeArgs =
                new DatabaseApplyingEventArgs(this.ProviderTypeName, context.SyncStage, configuration);

            this.TryRaiseProgressEvent(beforeArgs, this.DatabaseApplying);

            // if config has been editer by user in event, save again
            this.SetCacheConfiguration(configuration);

            // If scope exists and lastdatetime sync is present, so database exists
            // Check if we don't have an OverwriteConfiguration (if true, we force the check)
            if (scopeInfo.LastSync.HasValue && !beforeArgs.OverwriteConfiguration)
            {
                return(context);
            }

            StringBuilder script = new StringBuilder();

            // Open the connection
            using (var connection = this.CreateConnection())
            {
                try
                {
                    await connection.OpenAsync();

                    using (var transaction = connection.BeginTransaction())
                    {
                        foreach (var dmTable in configuration)
                        {
                            var builder = GetDatabaseBuilder(dmTable);

                            // adding filter
                            this.AddFilters(configuration, dmTable, builder);

                            context.SyncStage = SyncStage.DatabaseTableApplying;
                            DatabaseTableApplyingEventArgs beforeTableArgs =
                                new DatabaseTableApplyingEventArgs(this.ProviderTypeName, context.SyncStage, dmTable.TableName);
                            this.TryRaiseProgressEvent(beforeTableArgs, this.DatabaseTableApplying);

                            string currentScript = null;
                            if (beforeArgs.GenerateScript)
                            {
                                currentScript  = builder.ScriptTable(connection, transaction);
                                currentScript += builder.ScriptForeignKeys(connection, transaction);
                                script.Append(currentScript);
                            }

                            builder.Create(connection, transaction);
                            builder.CreateForeignKeys(connection, transaction);

                            context.SyncStage = SyncStage.DatabaseTableApplied;
                            DatabaseTableAppliedEventArgs afterTableArgs =
                                new DatabaseTableAppliedEventArgs(this.ProviderTypeName, context.SyncStage, dmTable.TableName, currentScript);
                            this.TryRaiseProgressEvent(afterTableArgs, this.DatabaseTableApplied);
                        }

                        context.SyncStage = SyncStage.DatabaseApplied;
                        var afterArgs = new DatabaseAppliedEventArgs(this.ProviderTypeName, context.SyncStage, script.ToString());
                        this.TryRaiseProgressEvent(afterArgs, this.DatabaseApplied);

                        transaction.Commit();
                    }
                }
                catch (DbException dbex)
                {
                    throw SyncException.CreateDbException(context.SyncStage, dbex);
                }
                catch (Exception ex)
                {
                    if (ex is SyncException)
                    {
                        throw;
                    }
                    else
                    {
                        throw SyncException.CreateUnknowException(context.SyncStage, ex);
                    }
                }
                finally
                {
                    if (connection.State != ConnectionState.Closed)
                    {
                        connection.Close();
                    }
                }
                return(context);
            }
        }
Esempio n. 5
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);
                }
            }
        }