public async Task <int> BulkRemoveAsync(IQueryable <TEntity> queryable, bool filterKeys, List <object[]> keys)
        {
            ValidateCompositeKeys(keys);

            if (filterKeys)
            {
                if (PrimaryKey.IsCompositeKey)
                {
                    ValidateCompositeKeys(keys);

                    var keyNames     = PrimaryKey.Keys.Select(x => x.Name.ToString()).ToList();
                    var keyPredicate = Predicates.ContainsCompositeKeys <TEntity>(keyNames, keys);

                    DbContext.RemoveRange(queryable.Where(keyPredicate));
                }
                else
                {
                    var primKeys     = new HashSet <object>(keys.Select(k => k[0]));
                    var keyPredicate = Predicates.ContainsPrimaryKeys <TEntity>(PrimaryKey.Primary.Name, primKeys);

                    DbContext.RemoveRange(queryable.Where(keyPredicate));
                }
            }
            else
            {
                DbContext.RemoveRange(queryable);
            }

            var numDeleted = DbContext.SaveChanges();

            return(await Task.FromResult(numDeleted));
        }
        public async Task <int> BulkUpdateAsync(IQueryable <TEntity> queryable, List <object[]> keys, List <string> updateProperties, Func <object[], TEntity> updateFunc)
        {
            ValidateCompositeKeys(keys);

            List <TEntity> entities;

            if (PrimaryKey.IsCompositeKey)
            {
                ValidateCompositeKeys(keys);

                var keyNames     = PrimaryKey.Keys.Select(x => x.Name.ToString()).ToList();
                var keyPredicate = Predicates.ContainsCompositeKeys <TEntity>(keyNames, keys);

                entities = queryable.Where(keyPredicate).ToList();
            }
            else
            {
                var primKeys     = new HashSet <object>(keys.Select(k => k[0]));
                var keyPredicate = Predicates.ContainsPrimaryKeys <TEntity>(PrimaryKey.Primary.Name, primKeys);

                entities = queryable.Where(keyPredicate).ToList();
            }

            var updatePropDict = updateProperties.ToDictionary(key => key, value => typeof(TEntity).GetProperty(value));

            foreach (var entity in entities)
            {
                var key = PrimaryKey.IsCompositeKey
                    ? GetCompositeKey(entity)
                    : new object[] { GetPrimaryKey(entity) };

                var updatedEntity = updateFunc(key);

                foreach (var updateProp in updatePropDict)
                {
                    var propInfo = updatePropDict[updateProp.Key];

                    propInfo.SetValue(entity, propInfo.GetValue(updatedEntity));
                }
            }

            if (entities.Count > 0)
            {
                DbContext.SaveChanges();
            }

            return(await Task.FromResult(entities.Count));
        }
        public IQueryable <TEntity> Join(DbSet <TEntity> rootQuery, List <object[]> keys, char delimiter)
        {
            if (PrimaryKey.IsCompositeKey)
            {
                ValidateCompositeKeys(keys);

                var keyNames     = PrimaryKey.Keys.Select(x => x.Name.ToString()).ToList();
                var keyPredicate = Predicates.ContainsCompositeKeys <TEntity>(keyNames, keys);

                return(rootQuery.Where(keyPredicate));
            }
            else
            {
                var primKeys     = new HashSet <object>(keys.Select(k => k[0]));
                var keyPredicate = Predicates.ContainsPrimaryKeys <TEntity>(PrimaryKey.Primary.Name, primKeys);

                return(rootQuery.Where(keyPredicate));
            }
        }