Commit 89a52216 authored by tr's avatar tr

1、合并

parents b9a70198 73dcf14b
......@@ -5,5 +5,9 @@
1、操作说明:[模块列表][表信息]表格右键増行/删行,[表信息]可下拉批量删除。
2、保存:保存配置信息模块以及表信息。如需删除模块,请先删除表并保存后再删除模块保存。
3、刷新:刷新配置信息和错误消息
4、功能模块与业务模块联动:
1)单击切换功能模块时:业务模块自动显示(选择列√),焦点行定位到第一个(√)的行
2)单击"选择"列以外其他任意单元格,功能列表自动定位该业务模块所属功能模块(业务模块有关联功能模块)。
5、显示所有:业务列表显示所有模块; 显示选择:仅显示功能列表当前选中的功能所涉及到的业务模块。
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Xml;
namespace Tools.MyData
{
/// <summary>
/// The SqlHelper class is intended to encapsulate high performance, scalable best practices for
/// common uses of SqlClient.
/// </summary>
public sealed class SqlHelper
{
#region private utility methods & constructors
private const int TIMEOUT = 1000 * 60 * 10; //表示无限制等待。
//Since this class provides only static methods, make the default constructor private to prevent
//instances from being created with "new SqlHelper()".
private SqlHelper() { }
/// <summary>
/// This method is used to attach array of SqlParameters to a SqlCommand.
///
/// This method will assign a value of DbNull to any parameter with a direction of
/// InputOutput and a value of null.
///
/// This behavior will prevent default values from being used, but
/// this will be the less common case than an intended pure output parameter (derived as InputOutput)
/// where the user provided no input value.
/// </summary>
/// <param name="command">The command to which the parameters will be added</param>
/// <param name="commandParameters">an array of SqlParameters tho be added to command</param>
private static void AttachParameters(SqlCommand command, SqlParameter[] commandParameters)
{
foreach (SqlParameter p in commandParameters)
{
//check for derived output value with no value assigned
if ((p.Direction == ParameterDirection.InputOutput) && (p.Value == null))
{
p.Value = DBNull.Value;
}
command.Parameters.Add(p);
}
}
/// <summary>
/// This method assigns an array of values to an array of SqlParameters.
/// </summary>
/// <param name="commandParameters">array of SqlParameters to be assigned values</param>
/// <param name="parameterValues">array of objects holding the values to be assigned</param>
private static void AssignParameterValues(SqlParameter[] commandParameters, object[] parameterValues)
{
if ((commandParameters == null) || (parameterValues == null))
{
//do nothing if we get no data
return;
}
// we must have the same number of values as we pave parameters to put them in
if (commandParameters.Length != parameterValues.Length)
{
throw new ArgumentException("Parameter count does not match Parameter Value count.");
}
//iterate through the SqlParameters, assigning the values from the corresponding position in the
//value array
for (int i = 0, j = commandParameters.Length; i < j; i++)
{
commandParameters[i].Value = parameterValues[i];
}
}
/// <summary>
/// This method opens (if necessary) and assigns a connection, transaction, command type and parameters
/// to the provided command.
/// </summary>
/// <param name="command">the SqlCommand to be prepared</param>
/// <param name="connection">a valid SqlConnection, on which to execute this command</param>
/// <param name="transaction">a valid SqlTransaction, or 'null'</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParameters to be associated with the command or 'null' if no parameters are required</param>
private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters)
{
//if the provided connection is not open, we will open it
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
//associate the connection with the command
command.Connection = connection;
//set the command text (stored procedure name or SQL statement)
command.CommandText = commandText;
//if we were provided a transaction, assign it.
if (transaction != null)
{
command.Transaction = transaction;
}
//set the command type
command.CommandType = commandType;
//attach the command parameters if they are provided
if (commandParameters != null)
{
AttachParameters(command, commandParameters);
}
return;
}
#endregion private utility methods & constructors
/// <summary>
/// 获取数据连接字符窜。
/// </summary>
/// <returns></returns>
#region ExecuteNonQuery
/// <summary>
/// Execute a SqlCommand (that returns no resultset and takes no parameters) against the database specified in
/// the connection string.
/// </summary>
/// <remarks>
/// e.g.:
/// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders");
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteNonQuery(connectionString, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns no resultset) against the database specified in the connection string
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create & open a SqlConnection, and dispose of it after we are done.
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
//call the overload that takes a connection in place of the connection string
return ExecuteNonQuery(cn, commandType, commandText, commandParameters);
}
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns no resultset) against the database specified in
/// the connection string using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// int result = ExecuteNonQuery(connString, "PublishOrders", 24, 36);
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="spName">the name of the stored prcedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns no resultset and takes no parameters) against the provided SqlConnection.
/// </summary>
/// <remarks>
/// e.g.:
/// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders");
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteNonQuery(connection, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns no resultset) against the specified SqlConnection
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
cmd.CommandTimeout = TIMEOUT; //add by steven
PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
//finally, execute the command.
int retval = cmd.ExecuteNonQuery();
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
return retval;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified SqlConnection
/// using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// int result = ExecuteNonQuery(conn, "PublishOrders", 24, 36);
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(SqlConnection connection, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns no resultset and takes no parameters) against the provided SqlTransaction.
/// </summary>
/// <remarks>
/// e.g.:
/// int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders");
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteNonQuery(transaction, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns no resultset) against the specified SqlTransaction
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
cmd.CommandTimeout = TIMEOUT; //add by steven
PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
//finally, execute the command.
int retval = cmd.ExecuteNonQuery();
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
return retval;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified
/// SqlTransaction using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// int result = ExecuteNonQuery(conn, trans, "PublishOrders", 24, 36);
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(SqlTransaction transaction, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName);
}
}
#endregion ExecuteNonQuery
#region ExecuteDataSet
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in
/// the connection string.
/// </summary>
/// <remarks>
/// e.g.:
/// DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteDataset(connectionString, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create & open a SqlConnection, and dispose of it after we are done.
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
//call the overload that takes a connection in place of the connection string
return ExecuteDataset(cn, commandType, commandText, commandParameters);
}
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in
/// the connection string using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// DataSet ds = ExecuteDataset(connString, "GetOrders", 24, 36);
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(string connectionString, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection.
/// </summary>
/// <remarks>
/// e.g.:
/// DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteDataset(connection, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
//create the DataAdapter & DataSet
SqlDataAdapter da = new SqlDataAdapter(cmd);
//让命令一直执行,直到用户取消它
da.SelectCommand.CommandTimeout = TIMEOUT;
DataSet ds = new DataSet();
//fill the DataSet using default values for DataTable names, etc.
da.Fill(ds);
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
//return the dataset
return ds;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection
/// using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// DataSet ds = ExecuteDataset(conn, "GetOrders", 24, 36);
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(SqlConnection connection, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteDataset(connection, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteDataset(connection, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction.
/// </summary>
/// <remarks>
/// e.g.:
/// DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteDataset(transaction, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
//create the DataAdapter & DataSet
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
//fill the DataSet using default values for DataTable names, etc.
da.Fill(ds);
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
//return the dataset
return ds;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified
/// SqlTransaction using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// DataSet ds = ExecuteDataset(trans, "GetOrders", 24, 36);
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static DataSet ExecuteDataset(SqlTransaction transaction, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteDataset(transaction, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteDataset(transaction, CommandType.StoredProcedure, spName);
}
}
#endregion ExecuteDataSet
#region ExecuteReader
/// <summary>
/// this enum is used to indicate whether the connection was provided by the caller, or created by SqlHelper, so that
/// we can set the appropriate CommandBehavior when calling ExecuteReader()
/// </summary>
private enum SqlConnectionOwnership
{
/// <summary>Connection is owned and managed by SqlHelper</summary>
Internal,
/// <summary>Connection is owned and managed by the caller</summary>
External
}
/// <summary>
/// Create and prepare a SqlCommand, and call ExecuteReader with the appropriate CommandBehavior.
/// </summary>
/// <remarks>
/// If we created and opened the connection, we want the connection to be closed when the DataReader is closed.
///
/// If the caller provided the connection, we want to leave it to them to manage.
/// </remarks>
/// <param name="connection">a valid SqlConnection, on which to execute this command</param>
/// <param name="transaction">a valid SqlTransaction, or 'null'</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParameters to be associated with the command or 'null' if no parameters are required</param>
/// <param name="connectionOwnership">indicates whether the connection parameter was provided by the caller, or created by SqlHelper</param>
/// <returns>SqlDataReader containing the results of the command</returns>
private static SqlDataReader ExecuteReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, SqlConnectionOwnership connectionOwnership)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, transaction, commandType, commandText, commandParameters);
//create a reader
SqlDataReader dr;
// call ExecuteReader with the appropriate CommandBehavior
if (connectionOwnership == SqlConnectionOwnership.External)
{
dr = cmd.ExecuteReader();
}
else
{
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
return dr;
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the database specified in
/// the connection string.
/// </summary>
/// <remarks>
/// e.g.:
/// SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteReader(connectionString, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the database specified in the connection string
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create & open a SqlConnection
SqlConnection cn = new SqlConnection(connectionString);
cn.Open();
try
{
//call the private overload that takes an internally owned connection in place of the connection string
return ExecuteReader(cn, null, commandType, commandText, commandParameters, SqlConnectionOwnership.Internal);
}
catch (Exception e)
{
//if we fail to return the SqlDatReader, we need to close the connection ourselves
cn.Close();
throw e;
}
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the database specified in
/// the connection string using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// SqlDataReader dr = ExecuteReader(connString, "GetOrders", 24, 36);
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(string connectionString, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteReader(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteReader(connectionString, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection.
/// </summary>
/// <remarks>
/// e.g.:
/// SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteReader(connection, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//pass through the call to the private overload using a null transaction value and an externally owned connection
return ExecuteReader(connection, (SqlTransaction)null, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection
/// using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// SqlDataReader dr = ExecuteReader(conn, "GetOrders", 24, 36);
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(SqlConnection connection, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
AssignParameterValues(commandParameters, parameterValues);
return ExecuteReader(connection, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteReader(connection, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction.
/// </summary>
/// <remarks>
/// e.g.:
/// SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteReader(transaction, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//pass through to private overload, indicating that the connection is owned by the caller
return ExecuteReader(transaction.Connection, transaction, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified
/// SqlTransaction using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// SqlDataReader dr = ExecuteReader(trans, "GetOrders", 24, 36);
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>a SqlDataReader containing the resultset generated by the command</returns>
public static SqlDataReader ExecuteReader(SqlTransaction transaction, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
AssignParameterValues(commandParameters, parameterValues);
return ExecuteReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteReader(transaction, CommandType.StoredProcedure, spName);
}
}
#endregion ExecuteReader
#region ExecuteScalar
/// <summary>
/// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the database specified in
/// the connection string.
/// </summary>
/// <remarks>
/// e.g.:
/// int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount");
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteScalar(connectionString, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a 1x1 resultset) against the database specified in the connection string
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create & open a SqlConnection, and dispose of it after we are done.
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
//call the overload that takes a connection in place of the connection string
return ExecuteScalar(cn, commandType, commandText, commandParameters);
}
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the database specified in
/// the connection string using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// int orderCount = (int)ExecuteScalar(connString, "GetOrderCount", 24, 36);
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(string connectionString, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the provided SqlConnection.
/// </summary>
/// <remarks>
/// e.g.:
/// int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount");
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteScalar(connection, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a 1x1 resultset) against the specified SqlConnection
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
//execute the command & return the results
object retval = cmd.ExecuteScalar();
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
return retval;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified SqlConnection
/// using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// int orderCount = (int)ExecuteScalar(conn, "GetOrderCount", 24, 36);
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(SqlConnection connection, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteScalar(connection, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteScalar(connection, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns a 1x1 resultset and takes no parameters) against the provided SqlTransaction.
/// </summary>
/// <remarks>
/// e.g.:
/// int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount");
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteScalar(transaction, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a 1x1 resultset) against the specified SqlTransaction
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
//execute the command & return the results
object retval = cmd.ExecuteScalar();
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
return retval;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a 1x1 resultset) against the specified
/// SqlTransaction using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// int orderCount = (int)ExecuteScalar(trans, "GetOrderCount", 24, 36);
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an object containing the value in the 1x1 resultset generated by the command</returns>
public static object ExecuteScalar(SqlTransaction transaction, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteScalar(transaction, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteScalar(transaction, CommandType.StoredProcedure, spName);
}
}
#endregion ExecuteScalar
#region ExecuteXmlReader
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlConnection.
/// </summary>
/// <remarks>
/// e.g.:
/// XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
/// <returns>an XmlReader containing the resultset generated by the command</returns>
public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteXmlReader(connection, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the specified SqlConnection
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an XmlReader containing the resultset generated by the command</returns>
public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters);
//create the DataAdapter & DataSet
XmlReader retval = cmd.ExecuteXmlReader();
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
return retval;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified SqlConnection
/// using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// XmlReader r = ExecuteXmlReader(conn, "GetOrders", 24, 36);
/// </remarks>
/// <param name="connection">a valid SqlConnection</param>
/// <param name="spName">the name of the stored procedure using "FOR XML AUTO"</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an XmlReader containing the resultset generated by the command</returns>
public static XmlReader ExecuteXmlReader(SqlConnection connection, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName);
}
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset and takes no parameters) against the provided SqlTransaction.
/// </summary>
/// <remarks>
/// e.g.:
/// XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders");
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
/// <returns>an XmlReader containing the resultset generated by the command</returns>
public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText)
{
//pass through the call providing null for the set of SqlParameters
return ExecuteXmlReader(transaction, commandType, commandText, (SqlParameter[])null);
}
/// <summary>
/// Execute a SqlCommand (that returns a resultset) against the specified SqlTransaction
/// using the provided parameters.
/// </summary>
/// <remarks>
/// e.g.:
/// XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
/// <param name="commandText">the stored procedure name or T-SQL command using "FOR XML AUTO"</param>
/// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
/// <returns>an XmlReader containing the resultset generated by the command</returns>
public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
//create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);
//create the DataAdapter & DataSet
XmlReader retval = cmd.ExecuteXmlReader();
// detach the SqlParameters from the command object, so they can be used again.
cmd.Parameters.Clear();
return retval;
}
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns a resultset) against the specified
/// SqlTransaction using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// XmlReader r = ExecuteXmlReader(trans, "GetOrders", 24, 36);
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>a dataset containing the resultset generated by the command</returns>
public static XmlReader ExecuteXmlReader(SqlTransaction transaction, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName);
}
}
#endregion ExecuteXmlReader
}
/// <summary>
/// SqlHelperParameterCache provides functions to leverage a static cache of procedure parameters, and the
/// ability to discover parameters for stored procedures at run-time.
/// </summary>
public sealed class SqlHelperParameterCache
{
#region private methods, variables, and constructors
//Since this class provides only static methods, make the default constructor private to prevent
//instances from being created with "new SqlHelperParameterCache()".
private SqlHelperParameterCache() { }
private static Hashtable paramCache = Hashtable.Synchronized(new Hashtable());
/// <summary>
/// resolve at run time the appropriate set of SqlParameters for a stored procedure
/// </summary>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="includeReturnValueParameter">whether or not to include their return value parameter</param>
/// <returns></returns>
private static SqlParameter[] DiscoverSpParameterSet(string connectionString, string spName, bool includeReturnValueParameter)
{
using (SqlConnection cn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(spName, cn))
{
cn.Open();
cmd.CommandType = CommandType.StoredProcedure;
SqlCommandBuilder.DeriveParameters(cmd);
if (!includeReturnValueParameter)
{
cmd.Parameters.RemoveAt(0);
}
SqlParameter[] discoveredParameters = new SqlParameter[cmd.Parameters.Count]; ;
cmd.Parameters.CopyTo(discoveredParameters, 0);
return discoveredParameters;
}
}
//deep copy of cached SqlParameter array
private static SqlParameter[] CloneParameters(SqlParameter[] originalParameters)
{
SqlParameter[] clonedParameters = new SqlParameter[originalParameters.Length];
for (int i = 0, j = originalParameters.Length; i < j; i++)
{
clonedParameters[i] = (SqlParameter)((ICloneable)originalParameters[i]).Clone();
}
return clonedParameters;
}
#endregion private methods, variables, and constructors
#region caching functions
/// <summary>
/// add parameter array to the cache
/// </summary>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <param name="commandParameters">an array of SqlParamters to be cached</param>
public static void CacheParameterSet(string connectionString, string commandText, params SqlParameter[] commandParameters)
{
string hashKey = connectionString + ":" + commandText;
paramCache[hashKey] = commandParameters;
}
/// <summary>
/// retrieve a parameter array from the cache
/// </summary>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="commandText">the stored procedure name or T-SQL command</param>
/// <returns>an array of SqlParamters</returns>
public static SqlParameter[] GetCachedParameterSet(string connectionString, string commandText)
{
string hashKey = connectionString + ":" + commandText;
SqlParameter[] cachedParameters = (SqlParameter[])paramCache[hashKey];
if (cachedParameters == null)
{
return null;
}
else
{
return CloneParameters(cachedParameters);
}
}
#endregion caching functions
#region Parameter Discovery Functions
/// <summary>
/// Retrieves the set of SqlParameters appropriate for the stored procedure
/// </summary>
/// <remarks>
/// This method will query the database for this information, and then store it in a cache for future requests.
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <returns>an array of SqlParameters</returns>
public static SqlParameter[] GetSpParameterSet(string connectionString, string spName)
{
return GetSpParameterSet(connectionString, spName, false);
}
/// <summary>
/// Retrieves the set of SqlParameters appropriate for the stored procedure
/// </summary>
/// <remarks>
/// This method will query the database for this information, and then store it in a cache for future requests.
/// </remarks>
/// <param name="connectionString">a valid connection string for a SqlConnection</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="includeReturnValueParameter">a bool value indicating whether the return value parameter should be included in the results</param>
/// <returns>an array of SqlParameters</returns>
public static SqlParameter[] GetSpParameterSet(string connectionString, string spName, bool includeReturnValueParameter)
{
string hashKey = connectionString + ":" + spName + (includeReturnValueParameter ? ":include ReturnValue Parameter" : "");
SqlParameter[] cachedParameters;
cachedParameters = (SqlParameter[])paramCache[hashKey];
if (cachedParameters == null)
{
cachedParameters = (SqlParameter[])(paramCache[hashKey] = DiscoverSpParameterSet(connectionString, spName, includeReturnValueParameter));
}
return CloneParameters(cachedParameters);
}
#endregion Parameter Discovery Functions
}
}
......@@ -72,6 +72,7 @@
<DependentUpon>wEditBasic.cs</DependentUpon>
</Compile>
<Compile Include="MyData\DBHelper.cs" />
<Compile Include="MyData\SqlHelper.cs" />
<Compile Include="UI\wAutoClass.cs">
<SubType>Form</SubType>
</Compile>
......
......@@ -40,7 +40,14 @@
this.tsmiAddRow = new System.Windows.Forms.ToolStripMenuItem();
this.tsmiDelRow = new System.Windows.Forms.ToolStripMenuItem();
this.dgvBusinessModel = new System.Windows.Forms.DataGridView();
this.选择 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.panel3 = new System.Windows.Forms.Panel();
this.label5 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.panel1 = new System.Windows.Forms.Panel();
this.label1 = new System.Windows.Forms.Label();
......@@ -73,13 +80,8 @@
this.tstbLinkString = new System.Windows.Forms.ToolStripTextBox();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.tsbHelp = new System.Windows.Forms.ToolStripButton();
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.选择 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.ckbMode = new System.Windows.Forms.CheckBox();
this.rdbShowAll = new System.Windows.Forms.RadioButton();
this.rdbShowSelected = new System.Windows.Forms.RadioButton();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
......@@ -122,7 +124,7 @@
this.splitContainer1.Panel2.BackColor = System.Drawing.SystemColors.Control;
this.splitContainer1.Panel2.Controls.Add(this.splitContainer2);
this.splitContainer1.Size = new System.Drawing.Size(1169, 551);
this.splitContainer1.SplitterDistance = 364;
this.splitContainer1.SplitterDistance = 421;
this.splitContainer1.SplitterWidth = 6;
this.splitContainer1.TabIndex = 0;
//
......@@ -142,7 +144,7 @@
this.splitContainer3.Panel2.BackColor = System.Drawing.SystemColors.Control;
this.splitContainer3.Panel2.Controls.Add(this.dgvBusinessModel);
this.splitContainer3.Panel2.Controls.Add(this.panel3);
this.splitContainer3.Size = new System.Drawing.Size(364, 516);
this.splitContainer3.Size = new System.Drawing.Size(421, 516);
this.splitContainer3.SplitterDistance = 220;
this.splitContainer3.TabIndex = 2;
//
......@@ -160,7 +162,7 @@
this.dgvModule.Location = new System.Drawing.Point(0, 0);
this.dgvModule.Name = "dgvModule";
this.dgvModule.RowTemplate.Height = 23;
this.dgvModule.Size = new System.Drawing.Size(364, 220);
this.dgvModule.Size = new System.Drawing.Size(421, 220);
this.dgvModule.TabIndex = 1;
//
// Column3
......@@ -218,37 +220,92 @@
this.dgvBusinessModel.BackgroundColor = System.Drawing.SystemColors.Window;
this.dgvBusinessModel.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvBusinessModel.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.选择,
this.dataGridViewTextBoxColumn1,
this.dataGridViewTextBoxColumn2,
this.dataGridViewTextBoxColumn3,
this.dataGridViewTextBoxColumn4,
this.dataGridViewTextBoxColumn5,
this.选择});
this.dataGridViewTextBoxColumn5});
this.dgvBusinessModel.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgvBusinessModel.Location = new System.Drawing.Point(0, 35);
this.dgvBusinessModel.Name = "dgvBusinessModel";
this.dgvBusinessModel.RowTemplate.Height = 23;
this.dgvBusinessModel.Size = new System.Drawing.Size(364, 257);
this.dgvBusinessModel.Size = new System.Drawing.Size(421, 257);
this.dgvBusinessModel.TabIndex = 3;
//
// 选择
//
this.选择.DataPropertyName = "IsSelect";
this.选择.HeaderText = "选择";
this.选择.Name = "选择";
this.选择.Width = 60;
//
// dataGridViewTextBoxColumn1
//
this.dataGridViewTextBoxColumn1.DataPropertyName = "ModelID";
this.dataGridViewTextBoxColumn1.HeaderText = "模块ID";
this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
this.dataGridViewTextBoxColumn1.ReadOnly = true;
this.dataGridViewTextBoxColumn1.Width = 80;
//
// dataGridViewTextBoxColumn2
//
this.dataGridViewTextBoxColumn2.DataPropertyName = "ModelName";
this.dataGridViewTextBoxColumn2.HeaderText = "模块名称";
this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
this.dataGridViewTextBoxColumn2.ReadOnly = true;
//
// dataGridViewTextBoxColumn3
//
this.dataGridViewTextBoxColumn3.DataPropertyName = "BusinessObject";
this.dataGridViewTextBoxColumn3.HeaderText = "业务类";
this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
this.dataGridViewTextBoxColumn3.ReadOnly = true;
//
// dataGridViewTextBoxColumn4
//
this.dataGridViewTextBoxColumn4.DataPropertyName = "WinForm";
this.dataGridViewTextBoxColumn4.HeaderText = "业务窗体";
this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4";
this.dataGridViewTextBoxColumn4.ReadOnly = true;
//
// dataGridViewTextBoxColumn5
//
this.dataGridViewTextBoxColumn5.DataPropertyName = "Param";
this.dataGridViewTextBoxColumn5.HeaderText = "参数";
this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
this.dataGridViewTextBoxColumn5.ReadOnly = true;
//
// panel3
//
this.panel3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel3.Controls.Add(this.ckbMode);
this.panel3.Controls.Add(this.rdbShowSelected);
this.panel3.Controls.Add(this.rdbShowAll);
this.panel3.Controls.Add(this.label5);
this.panel3.Controls.Add(this.label3);
this.panel3.Dock = System.Windows.Forms.DockStyle.Top;
this.panel3.Location = new System.Drawing.Point(0, 0);
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size(364, 35);
this.panel3.Size = new System.Drawing.Size(421, 35);
this.panel3.TabIndex = 4;
//
// label5
//
this.label5.AutoSize = true;
this.label5.ForeColor = System.Drawing.SystemColors.ControlDark;
this.label5.Location = new System.Drawing.Point(100, 10);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(161, 12);
this.label5.TabIndex = 2;
this.label5.Text = "(选中表示与功能模块绑定)";
//
// label3
//
this.label3.Dock = System.Windows.Forms.DockStyle.Left;
this.label3.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.label3.Location = new System.Drawing.Point(0, 0);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(121, 33);
this.label3.Size = new System.Drawing.Size(128, 33);
this.label3.TabIndex = 0;
this.label3.Text = "(业务)模块列表";
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
......@@ -260,7 +317,7 @@
this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(364, 35);
this.panel1.Size = new System.Drawing.Size(421, 35);
this.panel1.TabIndex = 0;
//
// label1
......@@ -293,7 +350,7 @@
this.splitContainer2.Panel2.BackColor = System.Drawing.SystemColors.Control;
this.splitContainer2.Panel2.Controls.Add(this.dgvTableColumn);
this.splitContainer2.Panel2.Controls.Add(this.panel4);
this.splitContainer2.Size = new System.Drawing.Size(799, 551);
this.splitContainer2.Size = new System.Drawing.Size(742, 551);
this.splitContainer2.SplitterDistance = 191;
this.splitContainer2.SplitterWidth = 6;
this.splitContainer2.TabIndex = 2;
......@@ -313,7 +370,7 @@
this.dgvModuleTable.Location = new System.Drawing.Point(0, 35);
this.dgvModuleTable.Name = "dgvModuleTable";
this.dgvModuleTable.RowTemplate.Height = 23;
this.dgvModuleTable.Size = new System.Drawing.Size(799, 156);
this.dgvModuleTable.Size = new System.Drawing.Size(742, 156);
this.dgvModuleTable.TabIndex = 1;
//
// Id
......@@ -361,7 +418,7 @@
this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
this.panel2.Location = new System.Drawing.Point(0, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(799, 35);
this.panel2.Size = new System.Drawing.Size(742, 35);
this.panel2.TabIndex = 2;
//
// label2
......@@ -396,7 +453,7 @@
this.dgvTableColumn.Name = "dgvTableColumn";
this.dgvTableColumn.ReadOnly = true;
this.dgvTableColumn.RowTemplate.Height = 23;
this.dgvTableColumn.Size = new System.Drawing.Size(799, 319);
this.dgvTableColumn.Size = new System.Drawing.Size(742, 319);
this.dgvTableColumn.TabIndex = 1;
//
// 序号
......@@ -477,7 +534,7 @@
this.panel4.Dock = System.Windows.Forms.DockStyle.Top;
this.panel4.Location = new System.Drawing.Point(0, 0);
this.panel4.Name = "panel4";
this.panel4.Size = new System.Drawing.Size(799, 35);
this.panel4.Size = new System.Drawing.Size(742, 35);
this.panel4.TabIndex = 2;
//
// label4
......@@ -557,58 +614,28 @@
this.tsbHelp.Size = new System.Drawing.Size(76, 22);
this.tsbHelp.Text = "使用说明";
//
// dataGridViewTextBoxColumn1
//
this.dataGridViewTextBoxColumn1.DataPropertyName = "ModelID";
this.dataGridViewTextBoxColumn1.HeaderText = "模块ID";
this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
this.dataGridViewTextBoxColumn1.ReadOnly = true;
this.dataGridViewTextBoxColumn1.Width = 80;
//
// dataGridViewTextBoxColumn2
//
this.dataGridViewTextBoxColumn2.DataPropertyName = "ModelName";
this.dataGridViewTextBoxColumn2.HeaderText = "模块名称";
this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
this.dataGridViewTextBoxColumn2.ReadOnly = true;
//
// dataGridViewTextBoxColumn3
//
this.dataGridViewTextBoxColumn3.DataPropertyName = "BusinessObject";
this.dataGridViewTextBoxColumn3.HeaderText = "业务类";
this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
this.dataGridViewTextBoxColumn3.ReadOnly = true;
//
// dataGridViewTextBoxColumn4
//
this.dataGridViewTextBoxColumn4.DataPropertyName = "WinForm";
this.dataGridViewTextBoxColumn4.HeaderText = "业务窗体";
this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4";
this.dataGridViewTextBoxColumn4.ReadOnly = true;
//
// dataGridViewTextBoxColumn5
//
this.dataGridViewTextBoxColumn5.DataPropertyName = "Param";
this.dataGridViewTextBoxColumn5.HeaderText = "参数";
this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
this.dataGridViewTextBoxColumn5.ReadOnly = true;
//
// 选择
//
this.选择.DataPropertyName = "IsSelect";
this.选择.HeaderText = "选择";
this.选择.Name = "选择";
this.选择.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
//
// ckbMode
//
this.ckbMode.AutoSize = true;
this.ckbMode.Location = new System.Drawing.Point(199, 9);
this.ckbMode.Name = "ckbMode";
this.ckbMode.Size = new System.Drawing.Size(96, 16);
this.ckbMode.TabIndex = 1;
this.ckbMode.Text = "联动功能模块";
this.ckbMode.UseVisualStyleBackColor = true;
// rdbShowAll
//
this.rdbShowAll.AutoSize = true;
this.rdbShowAll.Location = new System.Drawing.Point(260, 8);
this.rdbShowAll.Name = "rdbShowAll";
this.rdbShowAll.Size = new System.Drawing.Size(71, 16);
this.rdbShowAll.TabIndex = 3;
this.rdbShowAll.TabStop = true;
this.rdbShowAll.Text = "显示全部";
this.rdbShowAll.UseVisualStyleBackColor = true;
//
// rdbShowSelected
//
this.rdbShowSelected.AutoSize = true;
this.rdbShowSelected.Location = new System.Drawing.Point(334, 8);
this.rdbShowSelected.Name = "rdbShowSelected";
this.rdbShowSelected.Size = new System.Drawing.Size(71, 16);
this.rdbShowSelected.TabIndex = 4;
this.rdbShowSelected.TabStop = true;
this.rdbShowSelected.Text = "显示选择";
this.rdbShowSelected.UseVisualStyleBackColor = true;
this.rdbShowSelected.CheckedChanged += new System.EventHandler(this.rdbShowSelected_CheckedChanged);
//
// wSysModule
//
......@@ -695,12 +722,14 @@
private System.Windows.Forms.DataGridView dgvBusinessModel;
private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.DataGridViewCheckBoxColumn 选择;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn4;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn5;
private System.Windows.Forms.DataGridViewCheckBoxColumn 选择;
private System.Windows.Forms.CheckBox ckbMode;
private System.Windows.Forms.RadioButton rdbShowAll;
private System.Windows.Forms.RadioButton rdbShowSelected;
}
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ using System.Windows.Forms;
using Tools.MyCommon;
using Tools.MyData;
using Tools.MyUtils;
using System.Data.SqlClient;
namespace Tools.UI
{
......@@ -24,7 +25,7 @@ namespace Tools.UI
bool _IsFirstLoad = true;
List<TQuery> tableList = null;
DataTable _dtBusinessMode = null;
private string strDbConn = null;
/// <summary>
/// 模块
......@@ -46,12 +47,13 @@ namespace Tools.UI
{
InitializeComponent();
dgvModule.MultiSelect = false; // 模块禁止多选,要删除只能挨个删除
dgvBusinessModel.MultiSelect = false;// 业务模块禁止多选,反向定位功能模块需要
dgvModuleTable.MultiSelect = true;// 明细表允许多选删除
}
private void wSysChecker_Load(object sender, EventArgs e)
{
this.SetConfig();
this.InitDefaultDbLink();
this.InitData();
this.InitUI();
this._IsFirstLoad = false;
......@@ -83,13 +85,15 @@ namespace Tools.UI
return;
}
this.dgvBusinessModel.DataSource = _dtBusinessMode = GetBusinessModel();
//设置数据源;子表格在父表格之前绑定,可以更好的利用父表格绑定时出发的行改变事件,进行子表格的数据的过滤
this.dgvModuleTable.DataSource = this._dtModuleTable = this._ds.Tables[this.T_ModuleTable];
this.dgvModule.DataSource = this._ds.Tables[this.T_Module];
this.dgvBusinessModel.DataSource = _dtBusinessMode = GetBusinessModel();
}
public override void InitUI()
{
//初始化数据表格
......@@ -112,9 +116,8 @@ namespace Tools.UI
dgvModuleTable.SelectionChanged += DgvModuleTable_SelectionChanged;
dgvModuleTable.DataError += DgvModuleTable_DataError;
dgvBusinessModel.SelectionChanged += DgvBusinessModel_SelectionChanged;
dgvBusinessModel.RowEnter += DgvBusinessModel_RowEnter;
dgvBusinessModel.CellValueChanged += DgvBusinessModel_CellValueChanged;
//上下文菜单-事件
this.tsmiAddRow.Click += TsmiAddRow_Click;
......@@ -128,19 +131,45 @@ namespace Tools.UI
//结束编辑
this.EndEdit();
//保存配置信息
bool b = false;
bool b = true;
if (this._ds.HasChanges())
{
b = this._db.SaveData(this._ds, this.tableList);
}
b = b && SaveModuleBusinessModel();
return b;
}
/// <summary>
/// 保存功能模块对业务的映射(使用)关系
/// </summary>
private bool SaveModuleBusinessModel()
{
var rows = _dtBusinessMode.Select("ModuleId is not null");
using (var conn = new SqlConnection(strDbConn))
{
SqlHelper.ExecuteNonQuery(conn, CommandType.Text, "Delete From Sys_ModuleBusinessModel");
Array.ForEach(rows, row =>
{
SqlParameter[] parameters = new SqlParameter[] {
new SqlParameter("ModuleId",row["ModuleId"]),
new SqlParameter("ModelId",row["ModelID"])
};
SqlHelper.ExecuteNonQuery(conn, CommandType.Text, "Insert Into Sys_ModuleBusinessModel(ModuleId,ModelId) Values(@ModuleId,@ModelId);", parameters);
});
}
return true;
}
/// <summary>
/// 设置配置信息
/// </summary>
private void SetConfig()
private void InitDefaultDbLink()
{
//读取配置信息
var dtSetting = new DataTable("AppSetting");
......@@ -152,6 +181,7 @@ namespace Tools.UI
{
this.tstbLinkString.Text = Utils.GetDbItemModel(link).ToString();
this.InitDBHelper(link); //初始化数据访问对象
this.strDbConn = link;
}
}
......@@ -159,6 +189,8 @@ namespace Tools.UI
private void TsbSave_Click(object sender, EventArgs e)
{
dgvBusinessModel.EndEdit(); // 解决焦点不移开CellValueChanged事件未及时触发的问题
if (!this.CheckDataSource())
return;
try
......@@ -185,6 +217,7 @@ namespace Tools.UI
{
//初始化数据访问对象
this.InitDBHelper(frm.LinkModel);
this.strDbConn = frm.LinkModel.LinkString;
//刷新界面
this.TsbRefresh_Click(null, null);
}
......@@ -201,18 +234,30 @@ namespace Tools.UI
/// <summary>
/// 选中行改变事件,需配合 SelectionMode = DataGridViewSelectionMode.FullRowSelect.
/// RowEnter 会触发多次
/// </summary>
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DgvModule_SelectionChanged(object sender, EventArgs e)
{
var selectRows = dgvModule.SelectedRows;
if (selectRows.Count == 1)
/*
功能模块切换:
1、表信息刷新 -- 表的列根据表实时获取
2、业务模块列表刷新, 只勾选使用该功能的模块,并显示在前面。
*/
var drDgvModuleSelected = GetDataGridViewSelectedDataRow(dgvModule);
if (drDgvModuleSelected != null)
{
var rowIndex = selectRows[0].Index;
var moduleId = this._ds.Tables[this.T_Module].DefaultView[rowIndex]["Id"];
var moduleId = drDgvModuleSelected["Id"];
// 1、刷新表信息
if (this._dtModuleTable != null) this._dtModuleTable.DefaultView.RowFilter = $"ModuleId = '{moduleId}'";
// 2、刷新业务模块的选择列,只勾选使用该功能模块的行 ModuleId
SetBusinessModelSelected((Guid)moduleId);
}
}
/// <summary>
......@@ -236,6 +281,7 @@ namespace Tools.UI
}
}
// 必填列未填写时会报错,需要处理
private void DgvModuleTable_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
......@@ -248,74 +294,89 @@ namespace Tools.UI
}
#region 业务模块表格相关事件
/*
1、RowEnter 事件在切换行并改变单元格值的时候,从(r1,c1) -> (r2,c2) 会触发2次。触发事件单元格分别是:c1,c2。
2、选择列禁止排序。在排序情况下,改变单元格的值时,该行立即“消失”进而根据行号取得的行已不是值改变的行,从而无法更改其所属功能模块。
3、显示所有/显示选择便于切换仅显示功能模块所涉及的业务模块。
*/
//
private void DgvBusinessModel_SelectionChanged(object sender, EventArgs e)
int currentRowIndex = 0; //
private void DgvBusinessModel_RowEnter(object sender, DataGridViewCellEventArgs e)
{
var selectRows = dgvModuleTable.SelectedRows;
if (ckbMode.Checked && selectRows.Count == 1) // 根据所选业务模块,反向定位功能模块,
/*
业务表格选择行改变、需要反向定位选中功能模块列表
*/
var drModuleSelected = GetDataGridViewSelectedDataRow(dgvModule);
if (drModuleSelected == null) return; // 以下操作只在功能模块单行选中时发生。
if (dgvBusinessModel.Columns[e.ColumnIndex].DataPropertyName != "IsSelect")
{ // 非选择列触发,反向定位功能模块
var drBusinessModel = GetDataGridViewSelectedDataRow(dgvBusinessModel);
if (drBusinessModel == null) return;
if (drBusinessModel["ModuleId"] != DBNull.Value)
{
var rows = _ds.Tables[T_Module].Select($"Id = '{drBusinessModel["ModuleId"]}'");
if (rows.Length == 1) //
{
var gridRow = GetDataGridViewRow(dgvModule, rows[0]);
if (gridRow != null)
gridRow.Selected = true;
}
}
}
else
{
var rowIndex = selectRows[0].Index;
currentRowIndex = e.RowIndex;
}
}
#endregion
/// <summary>
/// 获取表的列信息(系统查询)
/// 单元格改变事件
/// </summary>
/// <param name="tabName"></param>
/// <returns></returns>
private DataTable GetTableColumnFromSystem(string tabName)
/// <param name="sender"></param>
/// <param name="e"></param>
private void DgvBusinessModel_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
var sqlTableColumn = $@"Select 序号, 列名, 数据类型, 主键, 唯一标识, 索引, 允许空, 默认值, 说明
From
(Select d.name As 表名, a.colid As '序号', a.name As '列名',
Case When b.name In ('varchar', 'nvarchar', 'varbinary', 'decimal', 'numeric') Then
b.name + '(' + Cast(IsNull(Case b.name When 'int' Then Null When 'text' Then Null When 'datetime' Then Null Else ColumnProperty(a.id, a.name, 'PRECISION')End, '') As Varchar(5))
+ Case When b.name In ('decimal', 'numeric') Then ',' + Cast(ColumnProperty(a.id, a.name, 'Scale') As Varchar(5))Else '' End + ')' Else b.name End As '数据类型', Case ix.is_primary_key When 1 Then '√' Else '' End As '主键',
Case ix.is_unique When 1 Then '√' Else '' End As '唯一标识', Case When ix.name Is Null Then '' Else '√' End As '索引', (Case When a.isnullable = 1 Then '√' Else '' End) As '允许空',
Case When e.text Is Null Then ''
When Left(e.text, 2) = '((' Then Substring(e.text, 3, Len(e.text) - 4)
When Left(e.text, 1) = '(' Then Substring(e.text, 2, Len(e.text) - 2)Else e.text End As '默认值', Case ix.is_primary_key When 1 Then '自增主键' Else IsNull(f.value, '')End As '说明'
From sys.syscolumns a
Left Join sys.types b On a.xtype = b.user_type_id
Inner Join sys.sysobjects d On a.id = d.id And d.xtype = 'U' And d.name != 'dtproperties'
Left Join sys.syscomments e On a.cdefault = e.id
Left Join sys.extended_properties f On f.major_id = d.id And f.minor_id = a.colid
Left Join sys.extended_properties ft On ft.major_id = d.id And ft.minor_id = 0
Left Join sys.index_columns ixc On ixc.object_id = a.id And ixc.column_id = a.colid
Left Join sys.indexes ix On ix.object_id = ixc.object_id And ix.index_id = ixc.index_id) t
Where 表名 = '{tabName}'
Order By
表名, 序号;";
// 改变选择单元格的值,必须先切换到当前行。避免
if (dgvBusinessModel.Columns[e.ColumnIndex].Name == "选择" && currentRowIndex == e.RowIndex)
{
var objCell = (bool)dgvBusinessModel.SelectedRows[0].Cells[e.ColumnIndex].Value;
var dtBusinessModel = (dgvBusinessModel.DataSource as DataTable).Rows[e.RowIndex];
return _db.GetDataTable(sqlTableColumn, "TableColumn");
if (objCell)
{
var drDgvModuleSelected = GetDataGridViewSelectedDataRow(dgvModule);
if (drDgvModuleSelected != null)
{
dtBusinessModel["ModuleId"] = drDgvModuleSelected["Id"];
}
}
else
{
dtBusinessModel["ModuleId"] = DBNull.Value;
}
}
}
/// <summary>
/// 获取业务模块
/// 业务表格显示所有/选中
/// </summary>
/// <param name="tabName"></param>
/// <returns></returns>
private DataTable GetBusinessModel()
/// <param name="sender"></param>
/// <param name="e"></param>
private void rdbShowSelected_CheckedChanged(object sender, EventArgs e)
{
var sql = @" Select Distinct a.ID As ModelID, a.Name As ModelName, b.BusinessObject, b.WinForm, IsNull(b.Param, '') As Param, c.ModuleId, Case When c.ModuleId Is Null Then 0 Else 1 End As IsSelect
From dbo.SysBusinessModel a
Left Join dbo.SysFunction b On b.ModelID = a.ID And b.Name In ('Add') And Len(b.WinForm) > 1
Left Join dbo.Sys_ModuleBusinessModel c On c.ModelId = a.ID
Where Not Exists (Select 1 From SysBusinessModel Where PrevID = a.ID)
Order By a.ID; ";
return _db.GetDataTable(sql, "BusinessModel", false);
_dtBusinessMode.DefaultView.RowFilter = rdbShowSelected.Checked ? "IsSelect = 'true'" : "";
}
#endregion
#endregion
#region 上下文菜单-事件
......@@ -393,6 +454,7 @@ namespace Tools.UI
dgv.AutoGenerateColumns = false;
dgv.RowHeadersVisible = false;
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dgv.AllowUserToResizeRows = false; // 禁止该变行高
}
/// <summary>
/// 检查数据源
......@@ -414,8 +476,7 @@ namespace Tools.UI
/// <param name="ds"></param>
private void EndEdit()
{
if (this._ds == null)
return;
if (this._ds == null) return;
//数据表格界面提交
this.dgvModule.CommitEdit(DataGridViewDataErrorContexts.Display);
this.dgvModuleTable.CommitEdit(DataGridViewDataErrorContexts.Display);
......@@ -430,8 +491,127 @@ namespace Tools.UI
}
}
}
// _dtBusinessMode 不在ds中,放一起会受查询字段所在表格的列的not null影响导致查询失败
foreach (DataRow dataRow in _dtBusinessMode.Rows)
dataRow.EndEdit();
}
#region 私有扩展操作
#region 业务取数
/// <summary>
/// 获取表的列信息(系统查询)
/// </summary>
/// <param name="tabName"></param>
/// <returns></returns>
private DataTable GetTableColumnFromSystem(string tabName)
{
var sqlTableColumn = $@"Select 序号, 列名, 数据类型, 主键, 唯一标识, 索引, 允许空, 默认值, 说明
From
(Select d.name As 表名, a.colid As '序号', a.name As '列名',
Case When b.name In ('varchar', 'nvarchar', 'varbinary', 'decimal', 'numeric') Then
b.name + '(' + Cast(IsNull(Case b.name When 'int' Then Null When 'text' Then Null When 'datetime' Then Null Else ColumnProperty(a.id, a.name, 'PRECISION')End, '') As Varchar(5))
+ Case When b.name In ('decimal', 'numeric') Then ',' + Cast(ColumnProperty(a.id, a.name, 'Scale') As Varchar(5))Else '' End + ')' Else b.name End As '数据类型', Case ix.is_primary_key When 1 Then '√' Else '' End As '主键',
Case ix.is_unique When 1 Then '√' Else '' End As '唯一标识', Case When ix.name Is Null Then '' Else '√' End As '索引', (Case When a.isnullable = 1 Then '√' Else '' End) As '允许空',
Case When e.text Is Null Then ''
When Left(e.text, 2) = '((' Then Substring(e.text, 3, Len(e.text) - 4)
When Left(e.text, 1) = '(' Then Substring(e.text, 2, Len(e.text) - 2)Else e.text End As '默认值', Case ix.is_primary_key When 1 Then '自增主键' Else IsNull(f.value, '')End As '说明'
From sys.syscolumns a
Left Join sys.types b On a.xtype = b.user_type_id
Inner Join sys.sysobjects d On a.id = d.id And d.xtype = 'U' And d.name != 'dtproperties'
Left Join sys.syscomments e On a.cdefault = e.id
Left Join sys.extended_properties f On f.major_id = d.id And f.minor_id = a.colid
Left Join sys.extended_properties ft On ft.major_id = d.id And ft.minor_id = 0
Left Join sys.index_columns ixc On ixc.object_id = a.id And ixc.column_id = a.colid
Left Join sys.indexes ix On ix.object_id = ixc.object_id And ix.index_id = ixc.index_id) t
Where 表名 = '{tabName}'
Order By
表名, 序号;";
return _db.GetDataTable(sqlTableColumn, "TableColumn");
}
/// <summary>
/// 获取业务模块
/// </summary>
/// <param name="tabName"></param>
/// <returns></returns>
private DataTable GetBusinessModel()
{
var sql = @"Select Distinct a.ID As ModelID, a.Name As ModelName, b.BusinessObject, b.WinForm, IsNull(b.Param, '') As Param, c.ModuleId, cast( Case When c.ModuleId Is Null Then 0 Else 1 End as bit) As IsSelect
From dbo.SysBusinessModel a
Left Join dbo.SysFunction b On b.ModelID = a.ID And b.Name In ('Add') And Len(b.WinForm) > 1
Left Join dbo.Sys_ModuleBusinessModel c On c.ModelId = a.ID
Where Not Exists (Select 1 From SysBusinessModel Where PrevID = a.ID)
Order By a.ID; ";
return _db.GetDataTable(sql, "BusinessModel", false);
}
#endregion
/// <summary>
/// 设置业务模块选择状态。不触发选择事件
/// </summary>
/// <param name="moduleId"></param>
private void SetBusinessModelSelected(Guid? moduleId)
{
if (_dtBusinessMode == null) return;
var rowsSelected = _dtBusinessMode.Select("IsSelect =1 ");
SetSelected(rowsSelected, false);
var rowsModule = _dtBusinessMode.Select($"ModuleId = '{moduleId}' ");
SetSelected(rowsModule, true);
// 默认选中该功能业务模块的第一行
if (rowsModule.Length > 0) GetDataGridViewRow(dgvBusinessModel, rowsModule[0]).Selected = true;
}
private void SetSelected(DataRow[] rows, bool isSelete, string fieldName = "IsSelect")
{
Array.ForEach(rows, row => row[fieldName] = isSelete);
}
/// <summary>
/// 获取表格当前选中的数据行
/// </summary>
/// <param name="dataGridView"></param>
/// <returns></returns>
private DataRow GetDataGridViewSelectedDataRow(DataGridView dataGridView)
{
if (dataGridView == null || dataGridView.DataSource == null) return null;
var selectRows = dataGridView.SelectedRows;
if (selectRows.Count == 0) return null;
return ((DataRowView)selectRows[0].DataBoundItem).Row;
}
/// <summary>
/// 返回表格行
/// </summary>
/// <param name="dataGridView"></param>
/// <param name="dataRow"></param>
/// <returns></returns>
private DataGridViewRow GetDataGridViewRow(DataGridView dataGridView, DataRow dataRow)
{
if (dataGridView == null || dataGridView.DataSource == null) return null;
foreach (DataGridViewRow gridRow in dataGridView.Rows)
{
if (gridRow.DataBoundItem != null && (gridRow.DataBoundItem as DataRowView).Row == dataRow)
return gridRow;
}
return null;
}
#endregion
}
}
......@@ -132,6 +132,9 @@
<metadata name="contextMenu1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>127, 17</value>
</metadata>
<metadata name="选择.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
......@@ -147,9 +150,6 @@
<metadata name="dataGridViewTextBoxColumn5.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="选择.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Id.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
......@@ -192,52 +192,52 @@
<metadata name="说明.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="序号.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="选择.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="列名.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="数据类型.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="主键.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="dataGridViewTextBoxColumn3.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="唯一标识.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="dataGridViewTextBoxColumn4.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="索引.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="dataGridViewTextBoxColumn5.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="允许空.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="序号.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="默认值.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="列名.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="说明.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="数据类型.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="主键.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="唯一标识.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn3.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="索引.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn4.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="允许空.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn5.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="默认值.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="选择.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="说明.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment