Esempio n. 1
0
        /// <summary>
        /// Update the specified container
        /// </summary>
        /// <param name="data">The data to be updated</param>
        /// <param name="principal">The principal for authorization</param>
        /// <param name="mode">The mode of operation</param>
        /// <returns>The updated model</returns>
        public TModel Update(TModel data, TransactionMode mode, IPrincipal principal)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal);

            this.Updating?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort update for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection())
            {
                connection.Open();
                using (IDbTransaction tx = connection.BeginTransaction())
                    try
                    {
                        //connection.Connection.Open();
                        connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.UpdatedByKey ?? (data as BaseEntityData)?.CreatedByKey);

                        this.m_tracer.TraceVerbose("UPDATE {0}", data);

                        data = this.UpdateInternal(connection, data, principal);
                        connection.AddCacheCommit(data);
                        data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded

                        if (mode == TransactionMode.Commit)
                        {
                            tx.Commit();
                            foreach (var itm in connection.CacheOnCommit)
                            {
                                ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm);
                            }
                        }
                        else
                        {
                            tx.Rollback();
                        }

                        var args = new DataPersistedEventArgs <TModel>(data, mode, principal);

                        this.Updated?.Invoke(this, args);

                        return(data);
                    }
                    catch (DbException e)
                    {
#if DEBUG
                        this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                        this.m_tracer.TraceError("Error : {0}", e.Message);
#endif
                        tx?.Rollback();

                        this.TranslateDbException(e);
                        throw;
                    }
                catch (Exception e)
                {
#if DEBUG
                    this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                    this.m_tracer.TraceError("Error : {0}", e.Message);
#endif
                    tx?.Rollback();

                    // if the exception is key not found, we want the caller to know
                    // so that a potential insert can take place
                    if (e is KeyNotFoundException)
                    {
                        throw new KeyNotFoundException(e.Message, e);
                    }

                    // if the exception is anything else, we want to throw a data persistence exception
                    throw new DataPersistenceException(e.Message, e);
                }
                finally
                {
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Performs query logic
        /// </summary>
        /// <param name="query">The query</param>
        /// <param name="queryId">The query identifier</param>
        /// <param name="offset">The offset of the query</param>
        /// <param name="count">The total count to return</param>
        /// <param name="authContext">The authentication context</param>
        /// <param name="totalCount">The total results matching</param>
        /// <param name="fastQuery">True if fast querying should be performed</param>
        /// <returns>The matching results</returns>
        protected virtual IEnumerable <TModel> QueryInvoke(Expression <Func <TModel, bool> > query, Guid queryId, int offset, int?count, IPrincipal authContext, out int totalCount, bool fastQuery, ModelSort <TModel>[] orderBy)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }

#if DEBUG
            Stopwatch sw = new Stopwatch();
            sw.Start();
#endif

            QueryRequestEventArgs <TModel> preArgs = new QueryRequestEventArgs <TModel>(query, offset, count, queryId, authContext, orderBy);
            this.Querying?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort query {0}", query);
                totalCount = preArgs.TotalResults;
                return(preArgs.Results);
            }

            // Query object
            using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetReadonlyConnection())
                try
                {
                    connection.Open();

                    this.m_tracer.TraceVerbose("QUERY {0}", query);

                    // Is there an obsoletion item already specified?
                    if (fastQuery)
                    {
                        connection.AddData("loadFast", true);
                        connection.LoadState = LoadState.PartialLoad;
                    }
                    else
                    {
                        connection.LoadState = LoadState.FullLoad;
                    }

                    var results  = this.QueryInternal(connection, query, queryId, offset, count ?? 1000, out totalCount, authContext, true, orderBy);
                    var postData = new QueryResultEventArgs <TModel>(query, results.AsQueryable(), offset, count, totalCount, queryId, authContext);
                    this.Queried?.Invoke(this, postData);

                    var retVal = postData.Results.ToList();

                    // Add to cache
                    foreach (var i in retVal.AsParallel().Where(i => i != null))
                    {
                        connection.AddCacheCommit(i);
                    }

                    ApplicationServiceContext.Current.GetService <IThreadPoolService>()?.QueueUserWorkItem(o =>
                    {
                        foreach (var itm in (o as IEnumerable <IdentifiedData>))
                        {
                            ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm);
                        }
                    }, connection.CacheOnCommit.ToList());

                    this.m_tracer.TraceVerbose("Returning {0}..{1} or {2} results", offset, offset + (count ?? 1000), totalCount);

                    return(retVal);
                }
                catch (NotSupportedException e)
                {
                    throw new DataPersistenceException("Cannot perform LINQ query", e);
                }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error : {0}", e);
                throw;
            }
            finally
            {
#if DEBUG
                sw.Stop();
                this.m_tracer.TraceVerbose("Query {0} took {1} ms", query, sw.ElapsedMilliseconds);
#endif
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Insert the specified storage data
        /// </summary>
        /// <param name="data">The storage data to be inserted</param>
        /// <param name="principal">The authentication context</param>
        /// <param name="mode">The transaction control mode</param>
        /// <returns>The inserted data</returns>
        public TModel Insert(TModel data, TransactionMode mode, IPrincipal principal)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal);

            this.Inserting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort insert for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection())
            {
                connection.Open();
                using (IDbTransaction tx = connection.BeginTransaction())
                    try
                    {
                        connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.CreatedByKey ?? (data as BaseEntityData)?.CreatedByKey);
                        // Disable inserting duplicate classified objects
                        var existing = data.TryGetExisting(connection, principal, true);
                        if (existing != null)
                        {
                            throw new DuplicateNameException(data.Key?.ToString());
                        }
                        else
                        {
                            this.m_tracer.TraceVerbose("INSERT {0}", data);
                            data = this.InsertInternal(connection, data, principal);
                            connection.AddCacheCommit(data);
                        }
                        data.LoadState = LoadState.FullLoad; // We just persisted so it is fully loaded

                        if (mode == TransactionMode.Commit)
                        {
                            tx.Commit();
                            foreach (var itm in connection.CacheOnCommit)
                            {
                                ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm);
                            }
                        }
                        else
                        {
                            tx.Rollback();
                        }

                        var args = new DataPersistedEventArgs <TModel>(data, mode, principal);

                        this.Inserted?.Invoke(this, args);

                        return(data);
                    }
                    catch (DbException e)
                    {
#if DEBUG
                        this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                        this.m_tracer.TraceError("Error : {0}", e.Message);
#endif
                        tx?.Rollback();

                        this.TranslateDbException(e);
                        throw;
                    }
                catch (Exception e)
                {
                    this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data));

                    tx?.Rollback();
                    throw new DataPersistenceException(e.Message, e);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Obsolete the specified key data
        /// </summary>
        /// <param name="storageData">The storage data to be obsoleted</param>
        /// <param name="principal">The principal to use to obsolete</param>
        /// <param name="mode">The mode of obsoletion</param>
        /// <returns>The obsoleted record</returns>
        public TModel Obsolete(TModel data, TransactionMode mode, IPrincipal principal)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal);

            this.Obsoleting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort for {0}", data);
                return(data);
            }

            // Obsolete object
            using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection())
            {
                connection.Open();
                using (IDbTransaction tx = connection.BeginTransaction())
                    try
                    {
                        //connection.Connection.Open();

                        this.m_tracer.TraceVerbose("OBSOLETE {0}", data);
                        connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.ObsoletedByKey ?? (data as BaseEntityData)?.ObsoletedByKey);

                        data = this.ObsoleteInternal(connection, data, principal);
                        connection.AddCacheCommit(data);
                        if (mode == TransactionMode.Commit)
                        {
                            tx.Commit();
                            foreach (var itm in connection.CacheOnCommit)
                            {
                                ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Remove(itm.Key.Value);
                            }
                        }
                        else
                        {
                            tx.Rollback();
                        }

                        var args = new DataPersistedEventArgs <TModel>(data, mode, principal);

                        this.Obsoleted?.Invoke(this, args);

                        return(data);
                    }
                    catch (Exception e)
                    {
                        this.m_tracer.TraceError("Error : {0}", e);
                        tx?.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                finally
                {
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Get the specified resource
        /// </summary>
        /// <typeparam name="TIdentifier">The type of identifier</typeparam>
        /// <param name="containerId">The id of the identifier to get</param>
        /// <param name="principal">The security principal to execute as</param>
        /// <param name="loadFast">True if to skip loading of some properties</param>
        /// <returns>The loaded model</returns>
        public TModel Get(Guid containerId, Guid?containerVersion, bool loadFast, IPrincipal principal)
        {
            // Try the cache if available
            var guidIdentifier = containerId;

            var cacheItem = ApplicationServiceContext.Current.GetService <IDataCachingService>()?.GetCacheItem <TModel>(guidIdentifier) as TModel;

            if (loadFast && cacheItem != null)
            {
                return(cacheItem);
            }
            else
            {
#if DEBUG
                Stopwatch sw = new Stopwatch();
                sw.Start();
#endif

                DataRetrievingEventArgs <TModel> preArgs = new DataRetrievingEventArgs <TModel>(containerId, containerVersion, principal);
                this.Retrieving?.Invoke(this, preArgs);
                if (preArgs.Cancel)
                {
                    this.m_tracer.TraceWarning("Pre-Event handler indicates abort retrieve {0}", containerId);
                    return(null);
                }

                // Query object
                using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetReadonlyConnection())
                    try
                    {
                        connection.Open();
                        this.m_tracer.TraceVerbose("GET {0}", containerId);

                        if (loadFast)
                        {
                            connection.AddData("loadFast", true);
                            connection.LoadState = LoadState.PartialLoad;
                        }
                        else
                        {
                            connection.LoadState = LoadState.FullLoad;
                        }

                        var result   = this.GetInternal(connection, guidIdentifier, principal);
                        var postData = new DataRetrievedEventArgs <TModel>(result, principal);
                        this.Retrieved?.Invoke(this, postData);

                        foreach (var itm in connection.CacheOnCommit)
                        {
                            ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm);
                        }

                        return(result);
                    }
                    catch (NotSupportedException e)
                    {
                        throw new DataPersistenceException("Cannot perform LINQ query", e);
                    }
                catch (Exception e)
                {
                    this.m_tracer.TraceError("Error : {0}", e);
                    throw;
                }
                finally
                {
#if DEBUG
                    sw.Stop();
                    this.m_tracer.TraceVerbose("Retrieve took {0} ms", sw.ElapsedMilliseconds);
#endif
                }
            }
        }