Ejemplo n.º 1
0
        /// <summary>
        /// Performs a delete for the specified <paramref name="keys"/>.
        /// </summary>
        /// <typeparam name="T">The resultant <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The entity framework model <see cref="Type"/>.</typeparam>
        /// <param name="saveArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
        /// <param name="keys">The key values.</param>
        public async Task DeleteAsync <T, TModel>(EfDbArgs <T, TModel> saveArgs, params IComparable[] keys) where T : class, new() where TModel : class, new()
        {
            CheckSaveArgs(saveArgs);
            CheckKeys(saveArgs, keys);
            var efKeys = new object[keys.Length];

            for (int i = 0; i < saveArgs.Mapper.UniqueKey.Count; i++)
            {
                efKeys[i] = saveArgs.Mapper.UniqueKey[i].ConvertToDestValue(keys[i], Mapper.OperationTypes.Unspecified);
            }

            using (var db = new EfDbContextManager(saveArgs))
            {
                await EfDbInvoker <TDbContext> .Default.InvokeAsync(this, async() =>
                {
                    // A pre-read is required to get the row version for concurrency.
                    var em = (TModel)await db.DbContext.FindAsync(typeof(TModel), efKeys).ConfigureAwait(false);
                    if (em == null)
                    {
                        return;
                    }

                    db.DbContext.Remove(em);

                    if (saveArgs.SaveChanges)
                    {
                        await db.DbContext.SaveChangesAsync(true).ConfigureAwait(false);
                    }
                }, this).ConfigureAwait(false);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Performs a create for the value (reselects and/or automatically saves changes where specified).
        /// </summary>
        /// <typeparam name="T">The resultant <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The entity framework model <see cref="Type"/>.</typeparam>
        /// <param name="saveArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
        /// <param name="value">The value to insert.</param>
        /// <returns>The value (refreshed where specified).</returns>
        public async Task <T> CreateAsync <T, TModel>(EfDbArgs <T, TModel> saveArgs, T value) where T : class, new() where TModel : class, new()
        {
            CheckSaveArgs(saveArgs);

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (value is IChangeLog cl)
            {
                if (cl.ChangeLog == null)
                {
                    cl.ChangeLog = new ChangeLog();
                }

                cl.ChangeLog.CreatedBy   = ExecutionContext.HasCurrent ? ExecutionContext.Current.Username : ExecutionContext.EnvironmentUsername;
                cl.ChangeLog.CreatedDate = ExecutionContext.HasCurrent ? ExecutionContext.Current.Timestamp : Cleaner.Clean(DateTime.Now);
            }

            return(await Invoker.InvokeAsync(this, async() =>
            {
                var model = saveArgs.Mapper.MapToDest(value, Mapper.OperationTypes.Create) ?? throw new InvalidOperationException("Mapping to the EF entity must not result in a null value.");
                DbContext.Add(model);

                if (saveArgs.SaveChanges)
                {
                    await DbContext.SaveChangesAsync(true).ConfigureAwait(false);
                }

                return (saveArgs.Refresh) ? saveArgs.Mapper.MapToSrce(model, Mapper.OperationTypes.Get) ! : value;
            }, this).ConfigureAwait(false));
Ejemplo n.º 3
0
        /// <summary>
        /// Performs an update for the value (reselects and/or automatically saves changes where specified).
        /// </summary>
        /// <typeparam name="T">The resultant <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The entity framework model <see cref="Type"/>.</typeparam>
        /// <param name="saveArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
        /// <param name="value">The value to insert.</param>
        /// <returns>The value (refreshed where specified).</returns>
        public async Task <T> UpdateAsync <T, TModel>(EfDbArgs <T, TModel> saveArgs, T value) where T : class, new() where TModel : class, new()
        {
            CheckSaveArgs(saveArgs);

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (value is IChangeLog cl)
            {
                if (cl.ChangeLog == null)
                {
                    cl.ChangeLog = new ChangeLog();
                }

                cl.ChangeLog.UpdatedBy   = ExecutionContext.HasCurrent ? ExecutionContext.Current.Username : ExecutionContext.EnvironmentUsername;
                cl.ChangeLog.UpdatedDate = ExecutionContext.HasCurrent ? ExecutionContext.Current.Timestamp : DateTime.Now;
            }

            using (var db = new EfDbContextManager(saveArgs))
            {
                return(await EfDbInvoker <TDbContext> .Default.InvokeAsync(this, async() =>
                {
                    if (OnUpdatePreReadForNotFound)
                    {
                        // Check (find) if the entity exists.
                        var efKeys = new object[saveArgs.Mapper.UniqueKey.Count];
                        for (int i = 0; i < saveArgs.Mapper.UniqueKey.Count; i++)
                        {
                            var v = saveArgs.Mapper.UniqueKey[i].GetSrceValue(value, Mapper.OperationTypes.Unspecified);
                            efKeys[i] = saveArgs.Mapper.UniqueKey[i].ConvertToDestValue(v, Mapper.OperationTypes.Unspecified);
                        }

                        var em = (TModel)await db.DbContext.FindAsync(typeof(TModel), efKeys).ConfigureAwait(false);
                        if (em == null)
                        {
                            throw new NotFoundException();
                        }

                        // Remove the entity from the tracker before we attempt to update; otherwise, will use existing rowversion and concurrency will not work as expected.
                        db.DbContext.Remove(em);
                        db.DbContext.ChangeTracker.AcceptAllChanges();
                    }

                    var model = saveArgs.Mapper.MapToDest(value, Mapper.OperationTypes.Update);
                    db.DbContext.Update(model);

                    if (saveArgs.SaveChanges)
                    {
                        await db.DbContext.SaveChangesAsync(true).ConfigureAwait(false);
                    }

                    return (saveArgs.Refresh) ? saveArgs.Mapper.MapToSrce(model, Mapper.OperationTypes.Get) : value;
                }, this).ConfigureAwait(false));
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Check the consistency of the save arguments.
        /// </summary>
        private void CheckSaveArgs <T, TModel>(EfDbArgs <T, TModel> saveArgs) where T : class, new() where TModel : class, new()
        {
            if (saveArgs == null)
            {
                throw new ArgumentNullException(nameof(saveArgs));
            }

            if (saveArgs.Refresh && !saveArgs.SaveChanges)
            {
                throw new ArgumentException("The Refresh property cannot be set to true without the SaveChanges also being set to true (given the save will occur after this method call).", nameof(saveArgs));
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Checks keys provided and match against defined.
        /// </summary>
        private void CheckKeys <T, TModel>(EfDbArgs <T, TModel> args, IComparable[] keys) where T : class, new() where TModel : class, new()
        {
            if (keys == null || keys.Length == 0)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            if (keys.Length != args.Mapper.UniqueKey.Count)
            {
                throw new ArgumentException($"The specified keys count '{keys.Length}' does not match the Mapper UniqueKey count '{args.Mapper.UniqueKey.Count}'.", nameof(keys));
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Gets the entity for the specified <paramref name="keys"/> mapping from <typeparamref name="TModel"/> to <typeparamref name="T"/>.
        /// </summary>
        /// <typeparam name="T">The resultant <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The entity framework model <see cref="Type"/>.</typeparam>
        /// <param name="getArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
        /// <param name="keys">The key values.</param>
        /// <returns>The entity value where found; otherwise, <c>null</c>.</returns>
        public async Task <T?> GetAsync <T, TModel>(EfDbArgs <T, TModel> getArgs, params IComparable[] keys) where T : class, new() where TModel : class, new()
        {
            if (getArgs == null)
            {
                throw new ArgumentNullException(nameof(getArgs));
            }

            CheckKeys(getArgs, keys);
            var efKeys = new object[keys.Length];

            for (int i = 0; i < getArgs.Mapper.UniqueKey.Count; i++)
            {
                efKeys[i] = getArgs.Mapper.UniqueKey[i].ConvertToDestValue(keys[i], Mapper.OperationTypes.Unspecified) !;
            }

            return(await Invoker.InvokeAsync(this, async() =>
            {
                return await FindAsync(getArgs, efKeys).ConfigureAwait(false);
            }, this).ConfigureAwait(false));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Gets the entity for the specified <paramref name="keys"/> mapping from <typeparamref name="TModel"/> to <typeparamref name="T"/>.
        /// </summary>
        /// <typeparam name="T">The resultant <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The entity framework model <see cref="Type"/>.</typeparam>
        /// <param name="getArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
        /// <param name="keys">The key values.</param>
        /// <returns>The entity value where found; otherwise, <c>null</c>.</returns>
        public async Task <T> GetAsync <T, TModel>(EfDbArgs <T, TModel> getArgs, params IComparable[] keys) where T : class, new() where TModel : class, new()
        {
            if (getArgs == null)
            {
                throw new ArgumentNullException(nameof(getArgs));
            }

            CheckKeys(getArgs, keys);
            var efKeys = new object[keys.Length];

            for (int i = 0; i < getArgs.Mapper.UniqueKey.Length; i++)
            {
                efKeys[i] = getArgs.Mapper.UniqueKey[i].ConvertToDestValue(keys[i], Mapper.OperationTypes.Unspecified);
            }

            using (var db = new EfDbContextManager(this, getArgs))
            {
                return(await EfDbInvoker <TDbContext> .Default.InvokeAsync(this, async() =>
                {
                    return await FindAsync(db, getArgs, efKeys);
                }, this));
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Performs a create for the value (reselects and/or automatically saves changes where specified).
        /// </summary>
        /// <typeparam name="T">The resultant <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The entity framework model <see cref="Type"/>.</typeparam>
        /// <param name="saveArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
        /// <param name="value">The value to insert.</param>
        /// <returns>The value (refreshed where specified).</returns>
        public async Task <T> CreateAsync <T, TModel>(EfDbArgs <T, TModel> saveArgs, T value) where T : class, new() where TModel : class, new()
        {
            CheckSaveArgs(saveArgs);

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (value is IChangeLog cl)
            {
                if (cl.ChangeLog == null)
                {
                    cl.ChangeLog = new ChangeLog();
                }

                cl.ChangeLog.CreatedBy   = ExecutionContext.HasCurrent ? ExecutionContext.Current.Username : ExecutionContext.EnvironmentUsername;
                cl.ChangeLog.CreatedDate = ExecutionContext.HasCurrent ? ExecutionContext.Current.Timestamp : DateTime.Now;
            }

            using (var db = new EfDbContextManager(saveArgs))
            {
                return(await EfDbInvoker <TDbContext> .Default.InvokeAsync(this, async() =>
                {
                    var model = saveArgs.Mapper.MapToDest(value, Mapper.OperationTypes.Create);
                    db.DbContext.Add(model);

                    if (saveArgs.SaveChanges)
                    {
                        await db.DbContext.SaveChangesAsync(true).ConfigureAwait(false);
                    }

                    return (saveArgs.Refresh) ? saveArgs.Mapper.MapToSrce(model, Mapper.OperationTypes.Get) : value;
                }, this).ConfigureAwait(false));
            }
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Creates an <see cref="EfDbQuery{T, TModel, TDbContext}"/> to enable select-like capabilities.
 /// </summary>
 /// <typeparam name="T">The resultant <see cref="Type"/>.</typeparam>
 /// <typeparam name="TModel">The entity framework model <see cref="Type"/>.</typeparam>
 /// <param name="queryArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
 /// <param name="query">The function to further define the query.</param>
 /// <returns>A <see cref="EfDbQuery{T, TModel, TDbContext}"/>.</returns>
 public IEfDbQuery <T, TModel> Query <T, TModel>(EfDbArgs <T, TModel> queryArgs, Func <IQueryable <TModel>, IQueryable <TModel> >?query = null) where T : class, new() where TModel : class, new()
 {
     return(new EfDbQuery <T, TModel, TDbContext>(this, queryArgs, query));
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Performs the EF select single (find).
        /// </summary>
        private async Task <T> FindAsync <T, TModel>(EfDbContextManager db, EfDbArgs <T, TModel> args, object[] keys) where T : class, new() where TModel : class, new()
        {
            var model = await db.DbContext.FindAsync <TModel>(keys).ConfigureAwait(false);

            return(args.Mapper.MapToSrce(model, Mapper.OperationTypes.Get));
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EfDbQuery{T, TModel, TDbContext}"/> class.
 /// </summary>
 /// <param name="db">The <see cref="DbSet{TModel}"/>.</param>
 /// <param name="queryArgs">The <see cref="EfDbArgs{T, TModel}"/>.</param>
 /// <param name="query">A function to modify the underlying <see cref="IQueryable{TModel}"/>.</param>
 internal EfDbQuery(EfDbBase <TDbContext> db, EfDbArgs <T, TModel> queryArgs, Func <IQueryable <TModel>, IQueryable <TModel> > query = null)
 {
     _db       = db ?? throw new ArgumentNullException(nameof(db));
     QueryArgs = queryArgs ?? throw new ArgumentNullException(nameof(queryArgs));
     _query    = query;
 }