Пример #1
0
        /// <summary>
        /// Executes a sql statement on a given table in local SQL database.
        /// </summary>
        /// <param name="tableName">The name of the table.</param>
        /// <param name="sql">The SQL query to execute.</param>
        /// <param name="parameters">The query parameters.</param>
        /// <returns>The result of query.</returns>
        protected virtual IList <JObject> ExecuteQuery(string tableName, string sql, IDictionary <string, object> parameters)
        {
            TableDefinition table = GetTable(tableName);

            return(this.ExecuteQuery(table, sql, parameters));
        }
Пример #2
0
        private Task UpsertAsyncInternal(string tableName, IEnumerable <JObject> items, bool fromServer)
        {
            TableDefinition table = GetTable(tableName);

            var first = items.FirstOrDefault();

            if (first == null)
            {
                return(Task.FromResult(0));
            }

            // Get the columns which we want to map into the database.
            var columns = new List <ColumnDefinition>();

            foreach (var prop in first.Properties())
            {
                ColumnDefinition column;

                // If the column is coming from the server we can just ignore it,
                // otherwise, throw to alert the caller that they have passed an invalid column
                if (!table.TryGetValue(prop.Name, out column) && !fromServer)
                {
                    throw new InvalidOperationException(string.Format(Properties.Resources.SqlStore_ColumnNotDefined, prop.Name, tableName));
                }

                if (column != null)
                {
                    columns.Add(column);
                }
            }

            if (columns.Count == 0)
            {
                // no query to execute if there are no columns in the table
                return(Task.FromResult(0));
            }

            var mergeIntoSql      = String.Format("MERGE INTO {0} AS Target ", SqlHelpers.FormatTableName(tableName));
            var mergeAsSourceSql  = string.Format(" AS SOURCE ({0}) ", String.Join(", ", columns.Select(c => c.Name).Select(SqlHelpers.FormatMember)));
            var mergeConditionSql = string.Format(" ON Target.{0} = Source.{1} ", MobileServiceSystemColumns.Id, MobileServiceSystemColumns.Id);
            var whenMatchedSql    = String.Format(" WHEN MATCHED THEN UPDATE SET {0} ", String.Join(", ", columns.Select(c => c.Name).Select(c => SqlHelpers.FormatMember(c) + " = " + "Source." + SqlHelpers.FormatMember(c))));
            var whenNotMatchedSql = String.Format(" WHEN NOT MATCHED BY TARGET THEN INSERT ({0}) VALUES ({1}); ",
                                                  String.Join(", ", columns.Select(c => c.Name).Select(SqlHelpers.FormatMember)),
                                                  String.Join(", ", columns.Select(c => " Source." + SqlHelpers.FormatMember(c.Name))));

            // Use int division to calculate how many times this record will fit into our parameter quota
            int batchSize = MaxParametersPerUpsertQuery / columns.Count;

            if (batchSize == 0)
            {
                throw new InvalidOperationException(string.Format(Properties.Resources.SqlStore_TooManyColumns, MaxParametersPerUpsertQuery));
            }

            foreach (var batch in items.Split(maxLength: batchSize))
            {
                var mergeValues = new StringBuilder();
                var parameters  = new Dictionary <string, object>();

                foreach (JObject item in batch)
                {
                    AppendInsertValuesSql(mergeValues, parameters, columns, item);
                    mergeValues.Append(",");
                }

                if (parameters.Any())
                {
                    mergeValues.Remove(mergeValues.Length - 1, 1); // remove the trailing comma

                    var upsertSql = mergeIntoSql
                                    + string.Format("USING (VALUES {0})", mergeValues)
                                    + mergeAsSourceSql
                                    + mergeConditionSql
                                    + whenMatchedSql
                                    + whenNotMatchedSql;

                    this.ExecuteNonQuery(upsertSql, parameters);
                }
            }

            return(Task.FromResult(0));
        }