public void Delete <TEntity>(TEntity[] entities)
            where TEntity : IDbEntity, new()
        {
            const DbOperation operation = DbOperation.Delete;

            Type       entityType       = typeof(TEntity);
            DbTypeInfo entityDbTypeInfo = this.GetDbTypeInfo <TEntity>();

            if (!entityDbTypeInfo.DefaultEntity.DbOperations.ContainsKey(operation))
            {
                throw new InvalidOperationException(string.Format("Operation {0} is not supported by type {1}.", operation, entityType.Name));
            }

            DbOperationInfo operationInfo = entityDbTypeInfo.DefaultEntity.DbOperations[operation];

            using (DataTable entityTable = entityDbTypeInfo.SchemaInfo[operationInfo.ParameterType].Clone())
            {
                for (int i = 0; i < entities.Length; ++i)
                {
                    DataRow entityRow = entityTable.NewRow();
                    entities[i].PopulateDataRow(this, entityRow);
                    entityTable.Rows.Add(entityRow);
                }

                using (SqlCommand deleteCommand = new SqlCommand(operationInfo.Procedure, this.dbConnection))
                {
                    SqlParameter entityParameter = new SqlParameter()
                    {
                        ParameterName = operationInfo.ParameterName,
                        SqlDbType     = SqlDbType.Structured,
                        Value         = entityTable
                    };

                    deleteCommand.Parameters.Add(entityParameter);
                    deleteCommand.CommandType = CommandType.StoredProcedure;

                    bool connectionAlreadyOpen = (this.dbConnection.State == ConnectionState.Open);

                    if (!connectionAlreadyOpen)
                    {
                        this.dbConnection.Open();
                    }

                    try
                    {
                        deleteCommand.ExecuteNonQuery();
                    }
                    finally
                    {
                        if (!connectionAlreadyOpen)
                        {
                            this.dbConnection.Close();
                        }
                    }
                }
            }
        }
        public void Put <TEntity>(TEntity[] entities)
            where TEntity : IDbEntity, new()
        {
            const DbOperation operation = DbOperation.Put;
            Type       entityType       = typeof(TEntity);
            DbTypeInfo entityDbTypeInfo = this.GetDbTypeInfo <TEntity>();

            if (!entityDbTypeInfo.DefaultEntity.DbOperations.ContainsKey(operation))
            {
                throw new InvalidOperationException(string.Format("Operation {0} is not supported by type {1}.", operation, entityType.Name));
            }

            DbOperationInfo operationInfo = entityDbTypeInfo.DefaultEntity.DbOperations[operation];

            using (DataTable entityTable = entityDbTypeInfo.SchemaInfo[operationInfo.ParameterType].Clone())
            {
                for (int i = 0; i < entities.Length; ++i)
                {
                    DataRow entityRow = entityTable.NewRow();
                    entityRow[DbConnection.entityIdFieldName] = i;
                    entities[i].PopulateDataRow(this, entityRow);
                    entityTable.Rows.Add(entityRow);
                }

                using (DataTable entityUpdateTable = new DataTable())
                {
                    using (SqlCommand putCommand = new SqlCommand(operationInfo.Procedure, this.dbConnection))
                    {
                        SqlParameter entityParameter = new SqlParameter()
                        {
                            ParameterName = operationInfo.ParameterName,
                            SqlDbType     = SqlDbType.Structured,
                            Value         = entityTable
                        };

                        putCommand.Parameters.Add(entityParameter);
                        putCommand.CommandType = CommandType.StoredProcedure;

                        using (SqlDataAdapter putAdapter = new SqlDataAdapter(putCommand))
                        {
                            putAdapter.Fill(entityUpdateTable);
                        }
                    }

                    foreach (DataRow entityUpdateRow in entityUpdateTable.Rows)
                    {
                        int entityUpdateId = (int)entityUpdateRow[DbConnection.entityIdFieldName];
                        entities[entityUpdateId].PopulateEntity(this, entityUpdateRow);
                    }
                }
            }
        }
        public TEntity[] Get <TEntity>(params DbParameter[] parameters)
            where TEntity : IDbEntity, new()
        {
            const DbOperation operation = DbOperation.Get;
            Type       entityType       = typeof(TEntity);
            DbTypeInfo entityDbTypeInfo = this.GetDbTypeInfo <TEntity>();

            if (!entityDbTypeInfo.DefaultEntity.DbOperations.ContainsKey(operation))
            {
                throw new InvalidOperationException(string.Format("Operation {0} is not supported by type {1}.", operation, entityType.Name));
            }

            DbOperationInfo operationInfo = entityDbTypeInfo.DefaultEntity.DbOperations[operation];

            using (DataTable entityTable = new DataTable())
            {
                using (SqlCommand getCommand = new SqlCommand(operationInfo.Procedure, this.dbConnection))
                {
                    getCommand.CommandType = CommandType.StoredProcedure;

                    foreach (DbParameter parameter in parameters)
                    {
                        getCommand.Parameters.AddWithValue(parameter.Name, parameter.Value);
                    }

                    using (SqlDataAdapter getAdapter = new SqlDataAdapter(getCommand))
                    {
                        getAdapter.Fill(entityTable);
                    }
                }

                TEntity[] results = new TEntity[entityTable.Rows.Count];

                for (int i = 0; i < results.Length; ++i)
                {
                    TEntity entity = new TEntity();
                    entity.PopulateEntity(this, entityTable.Rows[i]);
                    results[i] = entity;
                }

                return(results);
            }
        }