/// <summary>
        /// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
        /// </summary>
        /// <typeparam name="T">Type to be updated</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToUpsert">Entity to be updated</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
        public async static Task <int> UpsertBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToUpsert,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            ) where T : class
        {
            var typeMeta = TypeMeta.Get <T>();

            return(await connection.MergeBulkAsync <T>(
                       entitiesToUpsert,
                       transaction,
                       commandTimeout,
                       sqlBulkCopy : sqlBulkCopy,
                       matched =>
            {
                matched.Action = MergeAction.Update;
                matched.Condition = typeMeta.PropertiesExceptKeyAndComputed.ColumnListDifferenceCheck();
            },
                       notMatchedByTarget =>
            {
                notMatchedByTarget.Action = MergeAction.Insert;
            }
                       ));
        }
        /// <summary>
        /// Inserts an entity into table "Ts" and returns identity id or number of inserted rows if inserting a list.
        /// </summary>
        /// <typeparam name="T">The type to insert.</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToInsert">Entity to insert, can be list of entities</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>Identity of inserted entity, or number of inserted rows if inserting a list</returns>
        public async static Task <int> InsertBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToInsert,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            ) where T : class
        {
            var meta = TypeMeta.Get <T>();

            var wasClosed = connection.State == ConnectionState.Closed;

            if (wasClosed)
            {
                connection.Open();
            }

            var insertedTableName = await connection.TransferBulkAsync(entitiesToInsert, transaction : transaction, sqlBulkCopy : sqlBulkCopy);

            var columnList = meta.PropertiesExceptKeyAndComputed.ColumnList();

            var query = $@"
                INSERT INTO {meta.TableName} ({columnList}) 
                SELECT {columnList} FROM {insertedTableName};
			"            ;

            var inserted = await connection.ExecuteAsync(query, commandTimeout, transaction);

            if (wasClosed)
            {
                connection.Close();
            }

            return(inserted);
        }
Beispiel #3
0
        /// <summary>
        /// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
        /// </summary>
        /// <typeparam name="T">Type to be updated</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToDelete">Entity to be updated</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
        public async static Task <int> DeleteBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToDelete,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            ) where T : class
        {
            var entityCount = entitiesToDelete.Count();

            if (entityCount == 0)
            {
                return(0);
            }

            if (entityCount == 1)
            {
                return(await connection.DeleteAsync(entitiesToDelete.First(), transaction : transaction, commandTimeout : commandTimeout) ? 1 : 0);
            }

            var typeMeta = TypeMeta.Get <T>();

            if (typeMeta.PropertiesKey.Count == 0 && typeMeta.PropertiesExplicit.Count == 0)
            {
                throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
            }

            var wasClosed = connection.State == ConnectionState.Closed;

            if (wasClosed)
            {
                connection.Open();
            }

            var insertedTableName = await connection.TransferBulkAsync(
                entitiesToDelete,
                typeMeta.TableName,
                typeMeta.PropertiesKeyAndExplicit,
                transaction : transaction,
                sqlBulkCopy : sqlBulkCopy
                );

            var query = $@"
				DELETE Target
				FROM
					{ insertedTableName } AS Source
					INNER JOIN { typeMeta.TableName } AS Target
						ON { typeMeta.PropertiesKeyAndExplicit.ColumnListEquals(" AND ") };
			"            ;

            var deleted = await connection.ExecuteAsync(query, commandTimeout : commandTimeout, transaction : transaction);

            if (wasClosed)
            {
                connection.Close();
            }

            return(deleted);
        }
 public ProxyTypeDescriptor(Type type)
 {
     Meta                = TypeMeta.Get(type);
     ProxyType           = typeof(PlatformProxy <>).MakeGenericType(type);
     _properties         = Meta.Members.Select(m => new ProxyPropertyDescriptor(this, m)).ToArray();
     _propertyCollection = new PropertyDescriptorCollection(_properties);
     _events             = new EventDescriptorCollection(type.GetEvents().Select(e => new ProxyEventDescriptor(e)).ToArray());
 }
        public MergeActionOptions <T> Insert()
        {
            var typeMeta = TypeMeta.Get <T>();

            Action = MergeAction.Insert;
            ColumnsByPropertyInfo(typeMeta.PropertiesExceptKeyAndComputed);

            return(this);
        }
Beispiel #6
0
        /// <summary>
        /// Merges entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
        /// </summary>
        /// <typeparam name="T">Type to be updated</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToMerge">Entity to be updated</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
        public async static Task <int> MergeBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToMerge,
            SqlTransaction transaction                          = null,
            int?commandTimeout                                  = null,
            Action <SqlBulkCopy> sqlBulkCopy                    = null,
            Action <MergeKeyOptions> key                        = null,
            Action <MergeActionOptions <T> > matched            = null,
            Action <MergeActionOptions <T> > notMatchedByTarget = null,
            Action <MergeActionOptions <T> > notMatchedBySource = null
            ) where T : class
        {
            if (entitiesToMerge == null)
            {
                throw new ArgumentNullException(nameof(entitiesToMerge));
            }

            var entityCount = entitiesToMerge.Count();

            if (entityCount == 0)
            {
                return(0);
            }

            var typeMeta = TypeMeta.Get <T>();

            if (typeMeta.PropertiesKey.Count == 0 && typeMeta.PropertiesExplicit.Count == 0)
            {
                throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
            }

            var result = await connection.Execute(
                entitiesToMerge,
                typeMeta.PropertiesExceptComputed,
                async (connection, transaction, source, parameters, properties) =>
            {
                var sb = new StringBuilder($@"
						MERGE INTO {typeMeta.TableName} AS Target
						USING {source} AS Source
						ON ({OnColumns(typeMeta, keyAction: key).ColumnListEquals(" AND ")})"
                                           );
                sb.AppendLine();

                MergeMatchResult.Matched.Format(typeMeta, matched, sb);
                MergeMatchResult.NotMatchedBySource.Format(typeMeta, notMatchedBySource, sb);
                MergeMatchResult.NotMatchedByTarget.Format(typeMeta, notMatchedByTarget, sb);
                //MergeOutputFormat(typeMeta.PropertiesKey.Union(typeMeta.PropertiesComputed).ToList(), sb);
                sb.Append(";");

                return(await connection.ExecuteAsync(sb.ToString(), param: parameters, commandTimeout: commandTimeout, transaction: transaction));
            },
                transaction : transaction
                );

            return(result.Sum());
        }
        public MergeActionOptions <T> Update()
        {
            var typeMeta = TypeMeta.Get <T>();

            Action = MergeAction.Update;
            ColumnsByPropertyInfo(typeMeta.PropertiesExceptKeyAndComputed);
            CheckConditionOnColumns();

            return(this);
        }
        /// <summary>
        /// Merges entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
        /// </summary>
        /// <typeparam name="T">Type to be updated</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToMerge">Entity to be updated</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
        public async static Task <int> MergeBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToMerge,
            SqlTransaction transaction                     = null,
            int?commandTimeout                             = null,
            Action <SqlBulkCopy> sqlBulkCopy               = null,
            Action <MergeActionOptions> matched            = null,
            Action <MergeActionOptions> notMatchedByTarget = null,
            Action <MergeActionOptions> notMatchedBySource = null
            ) where T : class
        {
            var typeMeta = TypeMeta.Get <T>();

            if (typeMeta.PropertiesKey.Count == 0 && typeMeta.PropertiesExplicit.Count == 0)
            {
                throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
            }

            var wasClosed = connection.State == System.Data.ConnectionState.Closed;

            if (wasClosed)
            {
                connection.Open();
            }

            var insertedTableName = await connection.TransferBulkAsync(
                entitiesToMerge,
                typeMeta.TableName,
                typeMeta.Properties,
                transaction : transaction,
                sqlBulkCopy : sqlBulkCopy
                );

            var sb = new StringBuilder($@"
				MERGE INTO {typeMeta.TableName} AS Target
				USING {insertedTableName} AS Source
				ON ({typeMeta.PropertiesKeyAndExplicit.ColumnListEquals(" AND ")})"
                                       );

            MergeMatchResult.Matched.Format(typeMeta, matched, sb);
            MergeMatchResult.NotMatchedBySource.Format(typeMeta, notMatchedBySource, sb);
            MergeMatchResult.NotMatchedByTarget.Format(typeMeta, notMatchedByTarget, sb);
            sb.Append(";");

            var merged = await connection.ExecuteAsync(sb.ToString(), commandTimeout : commandTimeout, transaction : transaction);

            if (wasClosed)
            {
                connection.Close();
            }

            return(merged);
        }
Beispiel #9
0
        /// <summary>
        /// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
        /// </summary>
        /// <typeparam name="T">Type to be updated</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToUpdate">Entity to be updated</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
        public async static Task <int> UpdateBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToUpdate,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            ) where T : class
        {
            entitiesToUpdate = entitiesToUpdate.Where(x => (x is SqlMapperExtensions.IProxy proxy && !proxy.IsDirty) || !(x is SqlMapperExtensions.IProxy));

            var entityCount = entitiesToUpdate.Count();

            if (entityCount == 0)
            {
                return(0);
            }

            if (entityCount == 1)
            {
                return(await connection.UpdateAsync(entitiesToUpdate.First(), transaction : transaction, commandTimeout : commandTimeout) ? 1 : 0);
            }

            var typeMeta = TypeMeta.Get <T>();

            if (typeMeta.PropertiesKey.Count == 0 && typeMeta.PropertiesExplicit.Count == 0)
            {
                throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
            }

            var result = await connection.Execute(
                entitiesToUpdate,
                typeMeta.PropertiesExceptComputed,
                async (connection, transaction, source, parameters, properties) =>
            {
                var query = $@"
						UPDATE Target
						SET
							{ typeMeta.PropertiesExceptKeyAndComputed.ColumnListEquals(", ") }
						FROM
							{ source } AS Source
							INNER JOIN { typeMeta.TableName } AS Target
								ON { typeMeta.PropertiesKeyAndExplicit.ColumnListEquals(" AND ") };
					"                    ;

                return(await connection.ExecuteAsync(query, param: parameters, commandTimeout: commandTimeout, transaction: transaction));
            },
                transaction : transaction
                );

            return(result.Sum());
        }
        public static ProxyXamlType Get(Type type)
        {
            var meta = TypeMeta.Get(type);

            lock (_cache)
            {
                ProxyXamlType result;
                if (!_cache.TryGetValue(type, out result))
                {
                    _cache[type] = result = new ProxyXamlType(meta);
                }
                return(result);
            }
        }
        /// <summary>
        /// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
        /// </summary>
        /// <typeparam name="T">Type to be updated</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToUpdate">Entity to be updated</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
        public async static Task <bool> UpdateBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToUpdate,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            ) where T : class
        {
            entitiesToUpdate = entitiesToUpdate.Where(x => x is SqlMapperExtensions.IProxy proxy && !proxy.IsDirty);
            if (!entitiesToUpdate.Any())
            {
                return(false);
            }

            var typeMeta = TypeMeta.Get <T>();

            if (typeMeta.PropertiesKey.Count == 0 && typeMeta.PropertiesExplicit.Count == 0)
            {
                throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
            }

            var wasClosed = connection.State == ConnectionState.Closed;

            if (wasClosed)
            {
                connection.Open();
            }

            var insertedTableName = await connection.TransferBulkAsync(entitiesToUpdate, transaction : transaction, sqlBulkCopy : sqlBulkCopy);

            var query = $@"
				UPDATE Target
				SET
					{ typeMeta.PropertiesExceptKeyAndComputed.ColumnListEquals(", ") }
				FROM
					{ insertedTableName } AS Source
					INNER JOIN { typeMeta.TableName } AS Target
						ON { typeMeta.PropertiesKeyAndExplicit.ColumnListEquals(" AND ") };
			"            ;

            var updated = await connection.ExecuteAsync(query, commandTimeout : commandTimeout, transaction : transaction);

            if (wasClosed)
            {
                connection.Close();
            }

            return(updated > 0);
        }
Beispiel #12
0
        public async static Task <IEnumerable <T> > GetBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToGet,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            )
        {
            var typeMeta = TypeMeta.Get <T>();

            if (typeMeta.PropertiesKey.Count == 0 && typeMeta.PropertiesExplicit.Count == 0)
            {
                throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
            }

            var wasClosed = connection.State == ConnectionState.Closed;

            if (wasClosed)
            {
                connection.Open();
            }

            var insertedTableName = await connection.TransferBulkAsync(
                entitiesToGet,
                typeMeta.TableName,
                typeMeta.PropertiesKeyAndExplicit,
                transaction : transaction,
                sqlBulkCopy : sqlBulkCopy
                );

            var query = $@"
				SELECT *
				FROM
					{ insertedTableName } AS Source
					INNER JOIN { typeMeta.TableName } AS Target
						ON { typeMeta.PropertiesKeyAndExplicit.ColumnListEquals(" AND ") };
			"            ;

            var enities = await connection.QueryAsync <T>(query, commandTimeout : commandTimeout, transaction : transaction);

            if (wasClosed)
            {
                connection.Close();
            }

            return(enities);
        }
Beispiel #13
0
        public static async Task <string> TransferBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToInsert,
            SqlTransaction transaction       = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            )
        {
            var meta = TypeMeta.Get <T>();

            return(await connection.TransferBulkAsync(
                       entitiesToInsert,
                       meta.TableName,
                       meta.Properties,
                       transaction : transaction,
                       sqlBulkCopy : sqlBulkCopy
                       ));
        }
Beispiel #14
0
        /// <summary>
        /// Inserts an entity into table "Ts" and returns identity id or number of inserted rows if inserting a list.
        /// </summary>
        /// <typeparam name="T">The type to insert.</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToInsert">Entity to insert, can be list of entities</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>Identity of inserted entity, or number of inserted rows if inserting a list</returns>
        public async static Task <int> InsertBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToInsert,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            ) where T : class
        {
            var entityCount = entitiesToInsert.Count();

            if (entityCount == 0)
            {
                return(0);
            }

            if (entityCount == 1)
            {
                return(await connection.InsertAsync(entitiesToInsert, transaction : transaction, commandTimeout : commandTimeout));
            }

            var typeMeta = TypeMeta.Get <T>();

            var result = await connection.Execute(
                entitiesToInsert,
                typeMeta.PropertiesExceptKeyAndComputed,
                async (connection, transaction, source, parameters, properties) =>
            {
                var columnList = properties.ColumnList();

                var query = $@"
							INSERT INTO {typeMeta.TableName} ({columnList}) 
							SELECT {columnList} FROM {source} AS Source;
						"                        ;

                return(await connection.ExecuteAsync(query, param: parameters, commandTimeout: commandTimeout, transaction: transaction));
            },
                transaction : transaction
                );

            return(result.Sum());
        }
Beispiel #15
0
        /// <summary>
        /// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
        /// </summary>
        /// <typeparam name="T">Type to be updated</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="entitiesToUpsert">Entity to be updated</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
        public async static Task <int> UpsertBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToUpsert,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null,
            Action <MergeKeyOptions> key     = null
            ) where T : class
        {
            var typeMeta = TypeMeta.Get <T>();

            return(await connection.MergeBulkAsync <T>(
                       entitiesToUpsert,
                       transaction,
                       commandTimeout,
                       sqlBulkCopy : sqlBulkCopy,
                       key : key,
                       matched : options => options.Update(),
                       notMatchedByTarget : options => options.Insert()
                       ));
        }
Beispiel #16
0
        public async static Task <IEnumerable <T> > GetBulkAsync <T>(
            this SqlConnection connection,
            IEnumerable <T> entitiesToGet,
            SqlTransaction transaction       = null,
            int?commandTimeout               = null,
            Action <SqlBulkCopy> sqlBulkCopy = null
            )
        {
            if (!entitiesToGet.Any())
            {
                return(new List <T>());
            }

            var typeMeta = TypeMeta.Get <T>();

            if (typeMeta.PropertiesKey.Count == 0 && typeMeta.PropertiesExplicit.Count == 0)
            {
                throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
            }

            var result = await connection.Execute(
                entitiesToGet,
                typeMeta.PropertiesKeyAndExplicit,
                async (connection, transaction, source, parameters, properties) =>
            {
                var query = $@"
						SELECT *
						FROM
							{ source } AS Source
							INNER JOIN { typeMeta.TableName } AS Target
								ON { properties.ColumnListEquals(" AND ") };
					"                    ;

                return(await connection.QueryAsync <T>(query, param: parameters, commandTimeout: commandTimeout, transaction: transaction));
            },
                transaction : transaction
                );

            return(result.SelectMany(x => x.Select(y => y)));
        }
Beispiel #17
0
        public static async Task <int> TruncateAsync <T>(
            this SqlConnection connection
            )
        {
            var typeMeta = TypeMeta.Get <T>();

            var wasClosed = connection.State == ConnectionState.Closed;

            if (wasClosed)
            {
                connection.Open();
            }

            var result = await connection.ExecuteAsync($"TRUNCATE TABLE {typeMeta.TableName}");

            if (wasClosed)
            {
                connection.Close();
            }

            return(result);
        }