You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需Ajax且不刷新页面,如何更新交易列表GridView的新增/修改数据?

Got it, let's tackle your problem. You want your GridView to update in real-time without relying on traditional Ajax polling, supporting both incremental (new/modified records only) and full-load updates. Here are two solid approaches that fit your needs:

Solution Overview

Instead of client-initiated Ajax calls, we’ll use server-push technologies to send database changes directly to the client as they happen. This ensures instant updates while avoiding repetitive polling. Below are practical implementations tailored for ASP.NET (since you mentioned GridView):


SignalR is a mature library that simplifies real-time web communication, using WebSockets (or fallbacks like Server-Sent Events) to push updates from server to client. It’s perfect for your use case because it handles connection management and reconnections automatically.

Step 1: Set Up SignalR

  1. Install the SignalR NuGet package:
    Install-Package Microsoft.AspNet.SignalR
    
  2. Create a Hub class to manage communication:
    using Microsoft.AspNet.SignalR;
    
    public class TransactionHub : Hub
    {
        // Server-side method to broadcast updates to all clients
        public void BroadcastTransactionUpdates(object transactionData, bool isFullLoad)
        {
            Clients.All.ReceiveTransactionUpdates(transactionData, isFullLoad);
        }
    }
    
  3. Configure SignalR in your startup class:
    using Microsoft.Owin;
    using Owin;
    
    [assembly: OwinStartup(typeof(YourApp.Startup))]
    namespace YourApp
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.MapSignalR();
            }
        }
    }
    

Step 2: Trigger Updates on Database Changes

You need to notify SignalR whenever transactions are added or modified. Choose one of these methods:

  • Business Logic Hooks: Call the SignalR hub from your service layer right after saving a transaction:
    var hubContext = GlobalHost.ConnectionManager.GetHubContext<TransactionHub>();
    // Send incremental update (only new/modified records)
    hubContext.Clients.All.ReceiveTransactionUpdates(newOrModifiedTransactions, isFullLoad: false);
    // Send full load (all top 100 records) when needed
    hubContext.Clients.All.ReceiveTransactionUpdates(fullTransactionList, isFullLoad: true);
    
  • Database Triggers: Create SQL triggers that call a stored procedure to notify your application of changes (good if updates happen outside your app).
  • SQL Change Tracking: Use SQL Server’s built-in change tracking to periodically fetch modified records.

Step 3: Update GridView on the Client

Add SignalR scripts to your page and write JavaScript to handle incoming updates:

<script src="~/Scripts/jquery.signalR-2.4.3.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
    $(function () {
        var transactionHub = $.connection.transactionHub;

        // Client-side method to receive updates
        transactionHub.client.ReceiveTransactionUpdates = function (updatedData, isFullLoad) {
            var grid = $('#<%= YourGridView.ClientID %>');
            
            if (isFullLoad) {
                // Replace entire GridView content
                grid.empty();
                let tableHtml = '<thead><tr><th>ID</th><th>Amount</th><th>Date</th></tr></thead><tbody>';
                updatedData.forEach(item => {
                    tableHtml += `<tr data-id="${item.Id}"><td>${item.Id}</td><td>${item.Amount}</td><td>${item.TransactionDate}</td></tr>`;
                });
                tableHtml += '</tbody>';
                grid.html(tableHtml);
            } else {
                // Incremental update: add new rows or modify existing ones
                updatedData.forEach(item => {
                    const existingRow = grid.find(`tr[data-id="${item.Id}"]`);
                    if (existingRow.length) {
                        // Update existing row values
                        existingRow.find('td:eq(1)').text(item.Amount);
                        existingRow.find('td:eq(2)').text(item.TransactionDate);
                    } else {
                        // Add new row to the top (keep latest records first)
                        const newRow = `<tr data-id="${item.Id}"><td>${item.Id}</td><td>${item.Amount}</td><td>${item.TransactionDate}</td></tr>`;
                        grid.find('tbody').prepend(newRow);
                        // Trim to keep only top 100 records
                        if (grid.find('tbody tr').length > 100) {
                            grid.find('tbody tr:last').remove();
                        }
                    }
                });
            }
        };

        // Start the SignalR connection
        $.connection.hub.start().done(() => {
            console.log('Real-time connection established');
        });
    });
</script>

Approach 2: Server-Sent Events (SSE)

If you prefer a lighter-weight, standards-based option without SignalR, SSE uses a persistent HTTP connection to push updates from server to client. It’s simpler to set up for basic use cases.

Step 1: Create an SSE Endpoint

Add an action method in your controller to send SSE events:

using Newtonsoft.Json;
using System.Threading;

public ActionResult TransactionStream()
{
    Response.ContentType = "text/event-stream";
    Response.CacheControl = "no-cache";
    Response.BufferOutput = false;

    while (true)
    {
        // Check for new/modified transactions
        var updates = GetRecentTransactionChanges(); // Your custom method
        if (updates.Any())
        {
            var payload = JsonConvert.SerializeObject(new { Data = updates, IsFullLoad = false });
            Response.Write($"data: {payload}\n\n");
            Response.Flush();
        }

        // Periodically send full load (e.g., every 10 minutes)
        if (ShouldSendFullLoad()) // Your logic to trigger full load
        {
            var fullData = GetTop100Transactions();
            var fullPayload = JsonConvert.SerializeObject(new { Data = fullData, IsFullLoad = true });
            Response.Write($"data: {fullPayload}\n\n");
            Response.Flush();
        }

        Thread.Sleep(1000); // Wait 1 second before checking again
    }
}

Step 2: Client-Side SSE Handling

Add JavaScript to listen for SSE events and update the GridView:

<script>
    const eventSource = new EventSource('@Url.Action("TransactionStream")');
    
    eventSource.onmessage = function(event) {
        const update = JSON.parse(event.data);
        const grid = $('#<%= YourGridView.ClientID %>');
        
        if (update.IsFullLoad) {
            // Replace entire GridView
            grid.empty();
            let tableHtml = '<thead><tr><th>ID</th><th>Amount</th><th>Date</th></tr></thead><tbody>';
            update.Data.forEach(item => {
                tableHtml += `<tr data-id="${item.Id}"><td>${item.Id}</td><td>${item.Amount}</td><td>${item.TransactionDate}</td></tr>`;
            });
            tableHtml += '</tbody>';
            grid.html(tableHtml);
        } else {
            // Incremental update logic (same as SignalR example)
            update.Data.forEach(item => {
                const existingRow = grid.find(`tr[data-id="${item.Id}"]`);
                if (existingRow.length) {
                    existingRow.find('td:eq(1)').text(item.Amount);
                    existingRow.find('td:eq(2)').text(item.TransactionDate);
                } else {
                    const newRow = `<tr data-id="${item.Id}"><td>${item.Id}</td><td>${item.Amount}</td><td>${item.TransactionDate}</td></tr>`;
                    grid.find('tbody').prepend(newRow);
                    if (grid.find('tbody tr').length > 100) {
                        grid.find('tbody tr:last').remove();
                    }
                }
            });
        }
    };
    
    // Handle connection errors and reconnection
    eventSource.onerror = function(error) {
        console.error('SSE connection failed:', error);
        eventSource.close();
        // Reconnect after 5 seconds
        setTimeout(() => {
            eventSource = new EventSource('@Url.Action("TransactionStream")');
        }, 5000);
    };
</script>

Key Tips for Success

  • Performance: For incremental updates, only fetch records modified since the last update (use a timestamp or max ID filter to avoid full table scans).
  • Security: Ensure only authorized users can receive updates. SignalR supports authentication, and SSE uses your app’s existing auth system.
  • Initial Load: Load the first 100 transactions when the page renders, then rely on server-push for updates.

内容的提问来源于stack exchange,提问作者Balu Sidhartha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:51:40