Este artículo creará un DataGrid que contiene un control CheckBox. Este control permite a los usuarios seleccionar varias columnas para una exploración detallada. Si no hay forma de recuperar esta funcionalidad para SQL dinámico, entonces se debe utilizar la operación IN.
Al final del artículo, escribimos una función definida por el usuario (UDF) de SQL Server para dividir una cadena en subcadenas delimitadas. En este artículo, podemos ver cómo una UDF de este tipo puede resultar útil. Crearemos un formulario web donde el usuario podrá seleccionar algunos registros en el DataGrid seleccionando un control de casilla de verificación. Los detalles de estos registros verificados aparecerán en otro DataGrid del formulario. Este formulario se parece a la imagen de abajo.
A continuación se muestra el ASPX que utilizamos para crear el formulario. Nota: Cómo utilizar los controles TemplateColumn y Checkbox para aumentar las columnas de DataGrid. También utilizamos la propiedad DataKeyField de DataGrid para indicarle al objeto qué campo del registro de la base de datos contendrá el identificador de clave de la primera fila.
<id de formulario="Form1" método="publicación" runat="servidor">
<asp:DataGrid id="DataGrid1" runat="servidor"
AutoGenerateColumns="False" DataKeyField="ID de empleado">
<Columnas>
<asp:ColumnaPlantilla>
<Plantilla de artículo>
<asp:CheckBox runat="servidor" ID="EmpleadoCheckBox" />
</ItemTemplate>
</asp:ColumnaPlantilla>
<asp:ColumnaPlantilla>
<Plantilla de artículo>
<%# DataBinder.Eval(Container.DataItem, "Apellido") %>,
<%# DataBinder.Eval(Contenedor.DataItem, "Nombre") %>
</ItemTemplate>
</asp:ColumnaPlantilla>
</Columnas>
</asp:DataGrid>
<hr>
<asp:Button id="Pedidos" runat="servidor" Text="Ver pedidos"></asp:Button>
<hora>
<asp:DataGrid ID="DataGrid2" Runat="servidor" AutoGenerateColumns="True" />
</form>
Cuando el formulario se carga e inicializa, es necesario ensamblar el DataGrid superior. El código utiliza la biblioteca empresarial para acceder a la base de datos de ejemplo de SQL Sever Northwind y ejecuta la instrucción "SELECT EmployeeID, FirstName, LastName FROM Employees". El código para el evento de carga es el siguiente:
Private void Page_Load(remitente del objeto, System.EventArgs e)
{
si(!Página.IsPostBack)
{
Base de datos db = DatabaseFactory.CreateDatabase();
DBCommandWrapper dbCommandWrapper;
usando(dbCommandWrapper = db.GetSqlStringCommandWrapper(SELECT_EMPLOYEES))
{
usando (IDataReader dataReader = db.ExecuteReader(dbCommandWrapper))
{
DataGrid1.DataSource = lector de datos;
DataGrid1.DataBind();
}
}
}
}
Cuando el usuario hace clic en el botón "Pedidos", queremos mostrar una segunda tabla de datos que coincida con los de la base de datos con Empleados y esté relacionada con los datos de Pedidos. Una forma de hacerlo es crear SQL dinámico y utilizar la condición OR de todos los ID de empleado necesarios para la declaración WHERE.
El segundo método consiste en utilizar la operación IN de la declaración WHERE. La operación IN compara una lista de expresiones. Por ejemplo, la siguiente declaración devuelve información entre los IDS de empleado 7 y 4.
SELECCIONE EmpleadoID, Nombre, Apellido DE Empleados DONDE EmpleadoID EN (7, 4)
Conceptualmente, me gustaría usar un parámetro de cadena única para consultar los ID pasados, sin embargo, tal vez como una sola cadena, no se puede usar para la operación IN A parámetro de cadena única. En ese caso, la declaración SQL sería "DONDE Empleado EN ('7, 4')" y la base de datos devolvería un mensaje de error porque EmployeeID es de tipo int, no varchar.
Sin embargo, utilizamos la función de división construida en el artículo para separar la cadena en diferentes valores. Pasamos la cadena '7, 4' a la función split y obtendremos dos registros correspondientes a los valores 4 y 7. Una consulta SQL para seleccionar empleados y contar los totales de sus pedidos sería la siguiente:
SELECT count(*) AS Orders, E.FirstName, E.LastName
FROM Orders O
INNER JOIN Empleados E ON O.EmployeeID = E.EmployeeID
WHERE E.EmployeeID IN(SELECT Value FROM fn_Split(@employeeIDs, ','))
GROUP BY FirstName, LastName
ORDER BY count(*) DESC
Lo que se necesita para usar la consulta anterior es que se debe establecer y pasar el parámetro @employeeIDs. Este parámetro será una lista de ID separada por comas. Para construir esta cadena, para saber si el usuario seleccionó la fila, necesitamos usar un bucle que recorra en iteración el número de filas y marque cada control de casilla de verificación. Si el usuario selecciona una fila, la clave se guarda en empleado extrayendo el examinador de la propiedad DataKeys de la tabla (que se creó en el archivo ASPX para apuntar al campo EmployeeID).
cadena privada GetCheckedEmployeeIDs()
{
Delimitador de cadena = String.Empty;
ID de empleado de StringBuilder = nuevo StringBuilder();
para(int i = 0; i < DataGrid1.Items.Count; i++)
{
Casilla de verificación;
casilla de verificación = DataGrid1.Items[i].FindControl("EmployeeCheckBox") como CheckBox;
si (casilla de verificación! = nulo && casilla de verificación. Marcado == verdadero)
{
EmployeeIDs.Append(delimitador + DataGrid1.DataKeys[i].ToString());
delimitador = ",";
}
}
devolver ID de empleado.ToString();
}
El método anterior devuelve una cadena, como "10, 7, 20". El controlador de eventos de clic del botón Pedidos implicará un método que pasa información a SQL para obtener una lista de empleados y pedidos, y vincula los resultados en un segundo objeto DataGrid.
Private void Orders_Click (remitente del objeto, System.EventArgs e)
{
cadena ID de empleado = GetCheckedEmployeeID ();
Base de datos db = DatabaseFactory.CreateDatabase();
DBCommandWrapper dbCommandWrapper;
usando(dbCommandWrapper = db.GetSqlStringCommandWrapper(SELECT_ORDERS))
{
dbCommandWrapper.AddInParameter("@employeeIDs", DbType.String, EmployeeIDs);
usando (IDataReader dataReader = db.ExecuteReader(dbCommandWrapper))
{
DataGrid2.DataSource = lector de datos;
DataGrid2.DataBind();
}
}
}