Nota
O acceso a esta páxina require autorización. Pode tentar iniciar sesión ou modificar os directorios.
O acceso a esta páxina require autorización. Pode tentar modificar os directorios.
Una razón para implementar el modo virtual en el DataGridView control es recuperar los datos solo según sea necesario. Esto se denomina carga de datos justo a tiempo.
Si está trabajando con una tabla muy grande en una base de datos remota, por ejemplo, puede que quiera evitar retrasos de inicio recuperando solo los datos necesarios para mostrar y recuperar datos adicionales solo cuando el usuario desplaza nuevas filas a la vista. Si los equipos cliente que ejecutan la aplicación tienen una cantidad limitada de memoria disponible para almacenar datos, es posible que también desee descartar datos sin usar al recuperar nuevos valores de la base de datos.
En las secciones siguientes se describe cómo usar un DataGridView control con una memoria caché Just-In-Time.
Para copiar el código de este tema como un único listado, vea Cómo implementar el modo virtual con solo carga de datosIn-Time en el control Windows Forms DataGridView.
El formulario
En el ejemplo de código siguiente se define un formulario que contiene un control de solo DataGridView lectura que interactúa con un Cache objeto a través de un CellValueNeeded controlador de eventos. El Cache objeto administra los valores almacenados localmente y usa un DataRetriever objeto para recuperar valores de la tabla Orders de la base de datos Northwind de ejemplo. El DataRetriever objeto , que implementa la IDataPageRetriever interfaz requerida por la Cache clase , también se usa para inicializar las filas y columnas de DataGridView control.
Los IDataPageRetrievertipos , DataRetrievery Cache se describen más adelante en este tema.
Nota:
Almacenar información confidencial, como una contraseña, dentro de la cadena de conexión puede afectar a la seguridad de la aplicación. El uso de la autenticación de Windows (también conocido como seguridad integrada) es una manera más segura de controlar el acceso a una base de datos. Para obtener más información, consulte Protección de la información de conexión.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;
public class VirtualJustInTimeDemo : System.Windows.Forms.Form
{
private DataGridView dataGridView1 = new DataGridView();
private Cache memoryCache;
// Specify a connection string. Replace the given value with a
// valid connection string for a Northwind SQL Server sample
// database accessible to your system.
private string connectionString =
"Initial Catalog=NorthWind;Data Source=localhost;" +
"Integrated Security=SSPI;Persist Security Info=False";
private string table = "Orders";
protected override void OnLoad(EventArgs e)
{
// Initialize the form.
this.AutoSize = true;
this.Controls.Add(this.dataGridView1);
this.Text = "DataGridView virtual-mode just-in-time demo";
// Complete the initialization of the DataGridView.
this.dataGridView1.Size = new Size(800, 250);
this.dataGridView1.Dock = DockStyle.Fill;
this.dataGridView1.VirtualMode = true;
this.dataGridView1.ReadOnly = true;
this.dataGridView1.AllowUserToAddRows = false;
this.dataGridView1.AllowUserToOrderColumns = false;
this.dataGridView1.SelectionMode =
DataGridViewSelectionMode.FullRowSelect;
this.dataGridView1.CellValueNeeded += new
DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
// Create a DataRetriever and use it to create a Cache object
// and to initialize the DataGridView columns and rows.
try
{
DataRetriever retriever =
new DataRetriever(connectionString, table);
memoryCache = new Cache(retriever, 16);
foreach (DataColumn column in retriever.Columns)
{
dataGridView1.Columns.Add(
column.ColumnName, column.ColumnName);
}
this.dataGridView1.RowCount = retriever.RowCount;
}
catch (SqlException)
{
MessageBox.Show("Connection could not be established. " +
"Verify that the connection string is valid.");
Application.Exit();
}
// Adjust the column widths based on the displayed values.
this.dataGridView1.AutoResizeColumns(
DataGridViewAutoSizeColumnsMode.DisplayedCells);
base.OnLoad(e);
}
private void dataGridView1_CellValueNeeded(object sender,
DataGridViewCellValueEventArgs e)
{
e.Value = memoryCache.RetrieveElement(e.RowIndex, e.ColumnIndex);
}
[STAThreadAttribute()]
public static void Main()
{
Application.Run(new VirtualJustInTimeDemo());
}
}
Imports System.Data
Imports System.Data.SqlClient
Imports System.Drawing
Imports System.Windows.Forms
Public Class VirtualJustInTimeDemo
Inherits System.Windows.Forms.Form
Private WithEvents dataGridView1 As New DataGridView()
Private memoryCache As Cache
' Specify a connection string. Replace the given value with a
' valid connection string for a Northwind SQL Server sample
' database accessible to your system.
Private connectionString As String = _
"Initial Catalog=NorthWind;Data Source=localhost;" & _
"Integrated Security=SSPI;Persist Security Info=False"
Private table As String = "Orders"
Private Sub VirtualJustInTimeDemo_Load( _
ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Load
' Initialize the form.
With Me
.AutoSize = True
.Controls.Add(Me.dataGridView1)
.Text = "DataGridView virtual-mode just-in-time demo"
End With
' Complete the initialization of the DataGridView.
With Me.dataGridView1
.Size = New Size(800, 250)
.Dock = DockStyle.Fill
.VirtualMode = True
.ReadOnly = True
.AllowUserToAddRows = False
.AllowUserToOrderColumns = False
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
End With
' Create a DataRetriever and use it to create a Cache object
' and to initialize the DataGridView columns and rows.
Try
Dim retriever As New DataRetriever(connectionString, table)
memoryCache = New Cache(retriever, 16)
For Each column As DataColumn In retriever.Columns
dataGridView1.Columns.Add( _
column.ColumnName, column.ColumnName)
Next
Me.dataGridView1.RowCount = retriever.RowCount
Catch ex As SqlException
MessageBox.Show("Connection could not be established. " & _
"Verify that the connection string is valid.")
Application.Exit()
End Try
' Adjust the column widths based on the displayed values.
Me.dataGridView1.AutoResizeColumns( _
DataGridViewAutoSizeColumnsMode.DisplayedCells)
End Sub
Private Sub dataGridView1_CellValueNeeded( _
ByVal sender As Object, ByVal e As DataGridViewCellValueEventArgs) _
Handles dataGridView1.CellValueNeeded
e.Value = memoryCache.RetrieveElement(e.RowIndex, e.ColumnIndex)
End Sub
<STAThreadAttribute()> _
Public Shared Sub Main()
Application.Run(New VirtualJustInTimeDemo())
End Sub
End Class
Interfaz IDataPageRetriever
En el ejemplo de código siguiente se define la IDataPageRetriever interfaz, que se implementa mediante la DataRetriever clase . El único método declarado en esta interfaz es el SupplyPageOfData método , que requiere un índice de fila inicial y un recuento del número de filas en una sola página de datos. El implementador usa estos valores para recuperar un subconjunto de datos de un origen de datos.
Un Cache objeto usa una implementación de esta interfaz durante la construcción para cargar dos páginas iniciales de datos. Siempre que se necesite un valor sin almacenar en caché, la memoria caché descarta una de estas páginas y solicita una nueva página que contenga el valor de .IDataPageRetriever
public interface IDataPageRetriever
{
DataTable SupplyPageOfData(int lowerPageBoundary, int rowsPerPage);
}
Public Interface IDataPageRetriever
Function SupplyPageOfData( _
ByVal lowerPageBoundary As Integer, ByVal rowsPerPage As Integer) _
As DataTable
End Interface
La clase DataRetriever
En el ejemplo de código siguiente se define la DataRetriever clase , que implementa la IDataPageRetriever interfaz para recuperar páginas de datos de un servidor. La DataRetriever clase también proporciona Columns y RowCount propiedades, que el control DataGridView utiliza para crear las columnas necesarias y agregar la cantidad adecuada de filas vacías a la colección Rows. Es necesario agregar las filas vacías para que el control se comporte como si contiene todos los datos de la tabla. Esto significa que el cuadro de desplazamiento de la barra de desplazamiento tendrá el tamaño adecuado y el usuario podrá acceder a cualquier fila de la tabla. El controlador de eventos rellena las CellValueNeeded filas solo cuando se desplazan hacia la vista.
public class DataRetriever : IDataPageRetriever
{
private string tableName;
private SqlCommand command;
public DataRetriever(string connectionString, string tableName)
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
command = connection.CreateCommand();
this.tableName = tableName;
}
private int rowCountValue = -1;
public int RowCount
{
get
{
// Return the existing value if it has already been determined.
if (rowCountValue != -1)
{
return rowCountValue;
}
// Retrieve the row count from the database.
command.CommandText = "SELECT COUNT(*) FROM " + tableName;
rowCountValue = (int)command.ExecuteScalar();
return rowCountValue;
}
}
private DataColumnCollection columnsValue;
public DataColumnCollection Columns
{
get
{
// Return the existing value if it has already been determined.
if (columnsValue != null)
{
return columnsValue;
}
// Retrieve the column information from the database.
command.CommandText = "SELECT * FROM " + tableName;
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = command;
DataTable table = new DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.FillSchema(table, SchemaType.Source);
columnsValue = table.Columns;
return columnsValue;
}
}
private string commaSeparatedListOfColumnNamesValue = null;
private string CommaSeparatedListOfColumnNames
{
get
{
// Return the existing value if it has already been determined.
if (commaSeparatedListOfColumnNamesValue != null)
{
return commaSeparatedListOfColumnNamesValue;
}
// Store a list of column names for use in the
// SupplyPageOfData method.
System.Text.StringBuilder commaSeparatedColumnNames =
new System.Text.StringBuilder();
bool firstColumn = true;
foreach (DataColumn column in Columns)
{
if (!firstColumn)
{
commaSeparatedColumnNames.Append(", ");
}
commaSeparatedColumnNames.Append(column.ColumnName);
firstColumn = false;
}
commaSeparatedListOfColumnNamesValue =
commaSeparatedColumnNames.ToString();
return commaSeparatedListOfColumnNamesValue;
}
}
// Declare variables to be reused by the SupplyPageOfData method.
private string columnToSortBy;
private SqlDataAdapter adapter = new SqlDataAdapter();
public DataTable SupplyPageOfData(int lowerPageBoundary, int rowsPerPage)
{
// Store the name of the ID column. This column must contain unique
// values so the SQL below will work properly.
columnToSortBy ??= this.Columns[0].ColumnName;
if (!this.Columns[columnToSortBy].Unique)
{
throw new InvalidOperationException(String.Format(
"Column {0} must contain unique values.", columnToSortBy));
}
// Retrieve the specified number of rows from the database, starting
// with the row specified by the lowerPageBoundary parameter.
command.CommandText = "Select Top " + rowsPerPage + " " +
CommaSeparatedListOfColumnNames + " From " + tableName +
" WHERE " + columnToSortBy + " NOT IN (SELECT TOP " +
lowerPageBoundary + " " + columnToSortBy + " From " +
tableName + " Order By " + columnToSortBy +
") Order By " + columnToSortBy;
adapter.SelectCommand = command;
DataTable table = new DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.Fill(table);
return table;
}
}
Public Class DataRetriever
Implements IDataPageRetriever
Private tableName As String
Private command As SqlCommand
Public Sub New( _
ByVal connectionString As String, ByVal tableName As String)
Dim connection As New SqlConnection(connectionString)
connection.Open()
command = connection.CreateCommand()
Me.tableName = tableName
End Sub
Private rowCountValue As Integer = -1
Public ReadOnly Property RowCount() As Integer
Get
' Return the existing value if it has already been determined.
If Not rowCountValue = -1 Then
Return rowCountValue
End If
' Retrieve the row count from the database.
command.CommandText = "SELECT COUNT(*) FROM " & tableName
rowCountValue = CInt(command.ExecuteScalar())
Return rowCountValue
End Get
End Property
Private columnsValue As DataColumnCollection
Public ReadOnly Property Columns() As DataColumnCollection
Get
' Return the existing value if it has already been determined.
If columnsValue IsNot Nothing Then
Return columnsValue
End If
' Retrieve the column information from the database.
command.CommandText = "SELECT * FROM " & tableName
Dim adapter As New SqlDataAdapter()
adapter.SelectCommand = command
Dim table As New DataTable()
table.Locale = System.Globalization.CultureInfo.InvariantCulture
adapter.FillSchema(table, SchemaType.Source)
columnsValue = table.Columns
Return columnsValue
End Get
End Property
Private commaSeparatedListOfColumnNamesValue As String = Nothing
Private ReadOnly Property CommaSeparatedListOfColumnNames() As String
Get
' Return the existing value if it has already been determined.
If commaSeparatedListOfColumnNamesValue IsNot Nothing Then
Return commaSeparatedListOfColumnNamesValue
End If
' Store a list of column names for use in the
' SupplyPageOfData method.
Dim commaSeparatedColumnNames As New System.Text.StringBuilder()
Dim firstColumn As Boolean = True
For Each column As DataColumn In Columns
If Not firstColumn Then
commaSeparatedColumnNames.Append(", ")
End If
commaSeparatedColumnNames.Append(column.ColumnName)
firstColumn = False
Next
commaSeparatedListOfColumnNamesValue = _
commaSeparatedColumnNames.ToString()
Return commaSeparatedListOfColumnNamesValue
End Get
End Property
' Declare variables to be reused by the SupplyPageOfData method.
Private columnToSortBy As String
Private adapter As New SqlDataAdapter()
Public Function SupplyPageOfData( _
ByVal lowerPageBoundary As Integer, ByVal rowsPerPage As Integer) _
As DataTable Implements IDataPageRetriever.SupplyPageOfData
' Store the name of the ID column. This column must contain unique
' values so the SQL below will work properly.
If columnToSortBy Is Nothing Then
columnToSortBy = Me.Columns(0).ColumnName
End If
If Not Me.Columns(columnToSortBy).Unique Then
Throw New InvalidOperationException(String.Format( _
"Column {0} must contain unique values.", columnToSortBy))
End If
' Retrieve the specified number of rows from the database, starting
' with the row specified by the lowerPageBoundary parameter.
command.CommandText = _
"Select Top " & rowsPerPage & " " & _
CommaSeparatedListOfColumnNames & " From " & tableName & _
" WHERE " & columnToSortBy & " NOT IN (SELECT TOP " & _
lowerPageBoundary & " " & columnToSortBy & " From " & _
tableName & " Order By " & columnToSortBy & _
") Order By " & columnToSortBy
adapter.SelectCommand = command
Dim table As New DataTable()
table.Locale = System.Globalization.CultureInfo.InvariantCulture
adapter.Fill(table)
Return table
End Function
End Class
La clase Cache
En el ejemplo de código siguiente se define la Cache clase , que administra dos páginas de datos rellenadas a través de una IDataPageRetriever implementación. La Cache clase define una estructura interna DataPage, que contiene un DataTable para almacenar los valores en una única página de caché y que calcula los índices de fila que representan los límites superior e inferior.
La Cache clase carga dos páginas de datos durante su construcción. Cada vez que el CellValueNeeded evento solicita un valor, el Cache objeto determina si el valor está disponible en una de sus dos páginas y, si es así, lo devuelve. Si el valor no está disponible localmente, el Cache objeto determina cuál de sus dos páginas está más lejos de las filas mostradas actualmente y reemplaza la página por una nueva que contiene el valor solicitado, que luego devuelve.
Suponiendo que el número de filas de una página de datos sea el mismo que el número de filas que se pueden mostrar en pantalla a la vez, este modelo permite a los usuarios paginar a través de la tabla para volver eficazmente a la página más reciente vista.
public class Cache
{
private static int RowsPerPage;
// Represents one page of data.
public struct DataPage
{
public DataTable table;
private int lowestIndexValue;
private int highestIndexValue;
public DataPage(DataTable table, int rowIndex)
{
this.table = table;
lowestIndexValue = MapToLowerBoundary(rowIndex);
highestIndexValue = MapToUpperBoundary(rowIndex);
System.Diagnostics.Debug.Assert(lowestIndexValue >= 0);
System.Diagnostics.Debug.Assert(highestIndexValue >= 0);
}
public int LowestIndex
{
get
{
return lowestIndexValue;
}
}
public int HighestIndex
{
get
{
return highestIndexValue;
}
}
public static int MapToLowerBoundary(int rowIndex)
{
// Return the lowest index of a page containing the given index.
return (rowIndex / RowsPerPage) * RowsPerPage;
}
private static int MapToUpperBoundary(int rowIndex)
{
// Return the highest index of a page containing the given index.
return MapToLowerBoundary(rowIndex) + RowsPerPage - 1;
}
}
private DataPage[] cachePages;
private IDataPageRetriever dataSupply;
public Cache(IDataPageRetriever dataSupplier, int rowsPerPage)
{
dataSupply = dataSupplier;
Cache.RowsPerPage = rowsPerPage;
LoadFirstTwoPages();
}
// Sets the value of the element parameter if the value is in the cache.
private bool IfPageCached_ThenSetElement(int rowIndex,
int columnIndex, ref string element)
{
if (IsRowCachedInPage(0, rowIndex))
{
element = cachePages[0].table
.Rows[rowIndex % RowsPerPage][columnIndex].ToString();
return true;
}
else if (IsRowCachedInPage(1, rowIndex))
{
element = cachePages[1].table
.Rows[rowIndex % RowsPerPage][columnIndex].ToString();
return true;
}
return false;
}
public string RetrieveElement(int rowIndex, int columnIndex)
{
string element = null;
if (IfPageCached_ThenSetElement(rowIndex, columnIndex, ref element))
{
return element;
}
else
{
return RetrieveData_CacheIt_ThenReturnElement(
rowIndex, columnIndex);
}
}
private void LoadFirstTwoPages()
{
cachePages = new DataPage[]{
new DataPage(dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(0), RowsPerPage), 0),
new DataPage(dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(RowsPerPage),
RowsPerPage), RowsPerPage)};
}
private string RetrieveData_CacheIt_ThenReturnElement(
int rowIndex, int columnIndex)
{
// Retrieve a page worth of data containing the requested value.
DataTable table = dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(rowIndex), RowsPerPage);
// Replace the cached page furthest from the requested cell
// with a new page containing the newly retrieved data.
cachePages[GetIndexToUnusedPage(rowIndex)] = new DataPage(table, rowIndex);
return RetrieveElement(rowIndex, columnIndex);
}
// Returns the index of the cached page most distant from the given index
// and therefore least likely to be reused.
private int GetIndexToUnusedPage(int rowIndex)
{
if (rowIndex > cachePages[0].HighestIndex &&
rowIndex > cachePages[1].HighestIndex)
{
int offsetFromPage0 = rowIndex - cachePages[0].HighestIndex;
int offsetFromPage1 = rowIndex - cachePages[1].HighestIndex;
if (offsetFromPage0 < offsetFromPage1)
{
return 1;
}
return 0;
}
else
{
int offsetFromPage0 = cachePages[0].LowestIndex - rowIndex;
int offsetFromPage1 = cachePages[1].LowestIndex - rowIndex;
if (offsetFromPage0 < offsetFromPage1)
{
return 1;
}
return 0;
}
}
// Returns a value indicating whether the given row index is contained
// in the given DataPage.
private bool IsRowCachedInPage(int pageNumber, int rowIndex)
{
return rowIndex <= cachePages[pageNumber].HighestIndex &&
rowIndex >= cachePages[pageNumber].LowestIndex;
}
}
Public Class Cache
Private Shared RowsPerPage As Integer
' Represents one page of data.
Public Structure DataPage
Public table As DataTable
Private lowestIndexValue As Integer
Private highestIndexValue As Integer
Public Sub New(ByVal table As DataTable, ByVal rowIndex As Integer)
Me.table = table
lowestIndexValue = MapToLowerBoundary(rowIndex)
highestIndexValue = MapToUpperBoundary(rowIndex)
System.Diagnostics.Debug.Assert(lowestIndexValue >= 0)
System.Diagnostics.Debug.Assert(highestIndexValue >= 0)
End Sub
Public ReadOnly Property LowestIndex() As Integer
Get
Return lowestIndexValue
End Get
End Property
Public ReadOnly Property HighestIndex() As Integer
Get
Return highestIndexValue
End Get
End Property
Public Shared Function MapToLowerBoundary( _
ByVal rowIndex As Integer) As Integer
' Return the lowest index of a page containing the given index.
Return (rowIndex \ RowsPerPage) * RowsPerPage
End Function
Private Shared Function MapToUpperBoundary( _
ByVal rowIndex As Integer) As Integer
' Return the highest index of a page containing the given index.
Return MapToLowerBoundary(rowIndex) + RowsPerPage - 1
End Function
End Structure
Private cachePages As DataPage()
Private dataSupply As IDataPageRetriever
Public Sub New(ByVal dataSupplier As IDataPageRetriever, _
ByVal rowsPerPage As Integer)
dataSupply = dataSupplier
Cache.RowsPerPage = rowsPerPage
LoadFirstTwoPages()
End Sub
' Sets the value of the element parameter if the value is in the cache.
Private Function IfPageCached_ThenSetElement(ByVal rowIndex As Integer, _
ByVal columnIndex As Integer, ByRef element As String) As Boolean
If IsRowCachedInPage(0, rowIndex) Then
element = cachePages(0).table.Rows(rowIndex Mod RowsPerPage) _
.Item(columnIndex).ToString()
Return True
ElseIf IsRowCachedInPage(1, rowIndex) Then
element = cachePages(1).table.Rows(rowIndex Mod RowsPerPage) _
.Item(columnIndex).ToString()
Return True
End If
Return False
End Function
Public Function RetrieveElement(ByVal rowIndex As Integer, _
ByVal columnIndex As Integer) As String
Dim element As String = Nothing
If IfPageCached_ThenSetElement(rowIndex, columnIndex, element) Then
Return element
Else
Return RetrieveData_CacheIt_ThenReturnElement( _
rowIndex, columnIndex)
End If
End Function
Private Sub LoadFirstTwoPages()
cachePages = New DataPage() { _
New DataPage(dataSupply.SupplyPageOfData( _
DataPage.MapToLowerBoundary(0), RowsPerPage), 0), _
New DataPage(dataSupply.SupplyPageOfData( _
DataPage.MapToLowerBoundary(RowsPerPage), _
RowsPerPage), RowsPerPage) _
}
End Sub
Private Function RetrieveData_CacheIt_ThenReturnElement( _
ByVal rowIndex As Integer, ByVal columnIndex As Integer) As String
' Retrieve a page worth of data containing the requested value.
Dim table As DataTable = dataSupply.SupplyPageOfData( _
DataPage.MapToLowerBoundary(rowIndex), RowsPerPage)
' Replace the cached page furthest from the requested cell
' with a new page containing the newly retrieved data.
cachePages(GetIndexToUnusedPage(rowIndex)) = _
New DataPage(table, rowIndex)
Return RetrieveElement(rowIndex, columnIndex)
End Function
' Returns the index of the cached page most distant from the given index
' and therefore least likely to be reused.
Private Function GetIndexToUnusedPage(ByVal rowIndex As Integer) _
As Integer
If rowIndex > cachePages(0).HighestIndex AndAlso _
rowIndex > cachePages(1).HighestIndex Then
Dim offsetFromPage0 As Integer = _
rowIndex - cachePages(0).HighestIndex
Dim offsetFromPage1 As Integer = _
rowIndex - cachePages(1).HighestIndex
If offsetFromPage0 < offsetFromPage1 Then
Return 1
End If
Return 0
Else
Dim offsetFromPage0 As Integer = _
cachePages(0).LowestIndex - rowIndex
Dim offsetFromPage1 As Integer = _
cachePages(1).LowestIndex - rowIndex
If offsetFromPage0 < offsetFromPage1 Then
Return 1
End If
Return 0
End If
End Function
' Returns a value indicating whether the given row index is contained
' in the given DataPage.
Private Function IsRowCachedInPage( _
ByVal pageNumber As Integer, ByVal rowIndex As Integer) As Boolean
Return rowIndex <= cachePages(pageNumber).HighestIndex AndAlso _
rowIndex >= cachePages(pageNumber).LowestIndex
End Function
End Class
Consideraciones adicionales
Los ejemplos de código anteriores se proporcionan para demostrar la carga de datos justo a tiempo. Tendrá que modificar el código para sus propias necesidades para lograr la máxima eficiencia. Como mínimo, tendrá que elegir un valor adecuado para el número de filas por página de datos en la memoria caché. Este valor se pasa al Cache constructor . El número de filas por página no debe ser menor que el número de filas que se pueden mostrar simultáneamente en el DataGridView control.
Para obtener los mejores resultados, deberá realizar pruebas de rendimiento y pruebas de facilidad de uso para determinar los requisitos del sistema y los usuarios. Varios factores que deberá tener en cuenta incluyen la cantidad de memoria en las máquinas cliente que ejecutan la aplicación, el ancho de banda disponible de la conexión de red usada y la latencia del servidor usado. El ancho de banda y la latencia deben determinarse en momentos de uso máximo.
Para mejorar el rendimiento de desplazamiento de la aplicación, puede aumentar la cantidad de datos almacenados localmente. Sin embargo, para mejorar el tiempo de inicio, debe evitar cargar demasiados datos inicialmente. Es posible que quiera modificar la Cache clase para aumentar el número de páginas de datos que puede almacenar. El uso de más páginas de datos puede mejorar la eficacia de desplazamiento, pero deberá determinar el número ideal de filas en una página de datos, en función del ancho de banda disponible y de la latencia del servidor. Con páginas más pequeñas, se tendrá acceso al servidor con más frecuencia, pero tardará menos tiempo en devolver los datos solicitados. Si la latencia es más problemática que el ancho de banda, podría querer usar páginas de datos más grandes.
Consulte también
- DataGridView
- VirtualMode
- Optimización del rendimiento en el control DataGridView de Windows Forms
- Procedimientos recomendados para escalar el control DataGridView de Windows Forms
- Modo virtual en el control DataGridView de Windows Forms
- Guía: Implementación del modo virtual en el control DataGridView de Windows Forms
- Cómo: Implementar el modo virtual con la carga de datos Just-In-Time en el control DataGridView de formularios Windows Forms
.NET Desktop feedback