Skip to main content
All docs
V26.1
  • Bind Blazor Grid to Server Mode Data Sources

    • 14 minutes to read

    In Blazor Server applications, you can bind the DevExpress Blazor Grid component to Server Mode data sources. These data sources are designed to reduce memory consumption when working with large data collections.

    When bound to a Server Mode data source, the Grid loads data in small portions on demand (instead of the entire dataset). The component delegates all data shaping operations to underlying services (EF Core, XPO, and so on). These services process data more efficiently and enhance overall performance.

    You can run the following example to compare in-memory data binding and Server Mode data loading strategies: Server Mode Data Processing

    Data Source Types

    The Grid includes two types of Server Mode data sources:

    Server Mode Data Source
    A synchronous data source that locks UI and does not respond to user actions while data is retrieved.
    Instant Feedback Data Source
    An asynchronous data source that loads data in a background thread and does not freeze the UI. The Grid displays skeletons and data load indicators while data is retrieved.

    The following table lists cross-platform Server Mode data sources compatible with the Blazor Grid:

    Data Access Technology

    Server Mode Data Source

    Instant Feedback Data Source

    Entity Framework Core

    EntityServerModeSource

    EntityInstantFeedbackSource

    XPO

    XPServerCollectionSource

    XPServerModeView

    XPInstantFeedbackSource

    XPInstantFeedbackView

    Parallel LINQ

    PLinqServerModeSource

    PLinqInstantFeedbackSource

    OData

    ODataServerModeSource

    ODataInstantFeedbackSource

    How to Use Server Mode

    Follow these steps to use a Server Mode data source in the Grid:

    1. Add a reference to a data source namespace (for instance, DevExpress.Data.Linq for EF Core data sources).
    2. Create a data source instance and configure its parameters.
    3. Bind the data source instance to the Grid’s Data parameter.
    4. Implement the IDisposable interface on the Razor page (use the @implements directive). Within the page’s Dispose method, check the data source instance for null and dispose of it.

    The following sections contain code samples for different data access technologies.

    Bind to Data using Entity Framework Core

    For the EntityInstantFeedbackSource, you must specify the following data source parameters:

    KeyExpression
    Identifies the key property name in the entity model. If the database does not contain the primary key, you cannot use this database as a Server Mode data source.
    QueryableSource
    Defines a queryable data source from an EF Core data context (for instance, DbSet<T>).

    The following example binds the Grid to an EntityInstantFeedbackSource:

    @using InstantFeedback.Models;
    @using Microsoft.EntityFrameworkCore
    @using DevExpress.Data.Linq
    @inject IDbContextFactory<NorthwindContext> NorthwindContextFactory
    @implements IDisposable
    
    <DxGrid Data="InstantFeedbackSource"
            KeyFieldName="OrderId">
        <Columns>
            <DxGridDataColumn FieldName="ShipName" />
            <DxGridDataColumn FieldName="ShipCity" />
            <DxGridDataColumn FieldName="ShipCountry" />
            <DxGridDataColumn FieldName="Freight" />
            <DxGridDataColumn FieldName="OrderDate" />
            <DxGridDataColumn FieldName="ShippedDate" />
        </Columns>
    </DxGrid>
    @code {
        EntityInstantFeedbackSource InstantFeedbackSource { get; set; }
        NorthwindContext Northwind { get; set; }
    
        protected override void OnInitialized() {
            Northwind = NorthwindContextFactory.CreateDbContext();
            InstantFeedbackSource = new EntityInstantFeedbackSource(e => {
                e.KeyExpression = "OrderId";
                e.QueryableSource = Northwind.Orders;
            });
        }
        public void Dispose() {
            InstantFeedbackSource?.Dispose();
            Northwind?.Dispose();
        }
    }
    

    Blazor Grid Instant Feedback Source

    Run Demo: Grid - Large Dataset (Server Mode) Read Tutorial: Bind to Data with Entity Framework Core View Example: Bind to an Instant Feedback Data Source and Enable Edit Operations

    Bind to Data using OData

    The ODataInstantFeedbackSource includes the following mandatory settings:

    KeyExpression
    Specifies the key property name. To specify multiple columns of a composite key, pass a comma-separated or semicolon-separated list of key column names to this property.
    GetSource
    Handle this event to supply a queryable source connected to an OData service.

    The following code snippet binds the Grid to an ODataInstantFeedbackSource and activates edit operations:

    @using InstantFeedback.Models
    @using DevExpress.Data.ODataLinq
    @implements IDisposable
    
    <DxGrid EditMode="GridEditMode.EditRow"
            Data="ODataSource"
            KeyFieldName="Product_ID"
            EditModelSaving="OnEditModelSaving"
            DataItemDeleting="OnDataItemDeleting">
        <Columns>
            <DxGridCommandColumn />
            <DxGridDataColumn FieldName="Product_ID" Caption="ID" />
            <DxGridDataColumn FieldName="Product_Name" Caption="Product Name" />
            <DxGridDataColumn FieldName="Product_Cost" Caption="Unit Price" DisplayFormat="c" />
            <DxGridDataColumn FieldName="Product_Category" Caption="Category" />
        </Columns>
    </DxGrid>
    
    @code {
        ODataInstantFeedbackSource ODataSource { get; set; }
    
        protected override void OnInitialized() {
            ODataSource = new ODataInstantFeedbackSource();
            ODataSource.KeyExpression = "Product_ID";
            ODataSource.GetSource += (sender, e) => e.Query = new ProductsContext().Products;
        }
    
        async Task OnEditModelSaving(GridEditModelSavingEventArgs e) {
            var product = (Product)e.EditModel;
            var context = new ProductsContext();
            if (e.IsNew) {
                context.AddObject("Products", product);
            } else {
                context.AttachTo("Products", product);
                context.UpdateObject(product);
            }
            await Task.Run(() => context.SaveChanges());
        }
    
        async Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) {
            var id = (int)e.Grid.GetDataItemValue(e.DataItem, "Product_ID");
            var context = new ProductsContext();
            var product = new Product { Product_ID = id };
            context.AttachTo("Products", product);
            context.DeleteObject(product);
            await Task.Run(() => context.SaveChanges());
        }
    
        public void Dispose() {
            ODataSource?.Dispose();
        }
    }
    

    Bind Blazor Grid to Data using OData

    Bind to Data using XPO

    You must configure the following parameters for the XPInstantFeedbackSource:

    DisplayableProperties
    Lists semicolon-separated property names available for data binding.
    ResolveSession
    Handle this event to supply the XPInstantFeedbackSource with a Session connected to your data store.
    DismissSession
    Handle this event to dispose of the Session created in the ResolveSession event handler.

    The following code snippet binds the Grid to an XPInstantFeedbackSource and activates edit operations:

    @using DevExpress.Xpo;
    @inject CustomerService CustomerService
    @inject IDataLayer DataLayer
    @implements IDisposable
    
    <DxGrid Data="@instantFeedbackSource"
            KeyFieldName="Oid"
            EditMode="GridEditMode.EditRow"
            CustomizeEditModel="Grid_CustomizeEditModel"
            EditModelSaving="Grid_EditModelSaving"
            DataItemDeleting="Grid_DataItemDeleting">
        <Columns>
            <DxGridCommandColumn Width="110px" />
            <DxGridDataColumn Width="100px" FieldName="@nameof(Customer.Oid)" Caption="ID" ReadOnly="true" />
            <DxGridDataColumn FieldName="@nameof(Customer.FirstName)" />
            <DxGridDataColumn FieldName="@nameof(Customer.LastName)" />
        </Columns>
    </DxGrid>
    
    @code {
    
        XPInstantFeedbackSource instantFeedbackSource;
        string properties = $"{nameof(Customer.Oid)};{nameof(Customer.FirstName)};{nameof(Customer.LastName)}";
    
        protected override Task OnInitializedAsync() {
            instantFeedbackSource = new XPInstantFeedbackSource(typeof(Customer));
            instantFeedbackSource.DisplayableProperties = properties;
            instantFeedbackSource.ResolveSession += InstantFeedbackSource_ResolveSession;
            instantFeedbackSource.DismissSession += InstantFeedbackSource_DismissSession;
            return Task.CompletedTask;
        }
    
        void InstantFeedbackSource_ResolveSession(object sender, ResolveSessionEventArgs e) {
            e.Session = new Session(DataLayer);
        }
    
        void InstantFeedbackSource_DismissSession(object sender, ResolveSessionEventArgs e) {
            IDisposable session = e.Session as IDisposable;
            if (session != null)
                session.Dispose();
        }
        void Grid_CustomizeEditModel(GridCustomizeEditModelEventArgs e) {
            var customer = CustomerService.CreateObject();
            e.EditModel = customer;
            if (e.DataItem != null) {
                customer.Oid = (int)e.Grid.GetDataItemValue(e.DataItem, nameof(Customer.Oid));
                customer.FirstName = (string)e.Grid.GetDataItemValue(e.DataItem, nameof(Customer.FirstName));
                customer.LastName = (string)e.Grid.GetDataItemValue(e.DataItem, nameof(Customer.LastName));
            }
        }
        async void Grid_EditModelSaving(GridEditModelSavingEventArgs e) {
            Customer customer = null;
            customer = (Customer)e.EditModel;
            var customerChanges = GetCustomerChanges(customer);
            if (e.IsNew) {
                await CustomerService.Add(customerChanges);
            } else {
                await CustomerService.Update(customer.Oid, customerChanges);
            }
        }
        async void Grid_DataItemDeleting(GridDataItemDeletingEventArgs e) {
            var oid = (int)e.Grid.GetDataItemValue(e.DataItem, nameof(Customer.Oid));
            await CustomerService.Delete(oid);
        }
        private Dictionary<string, object> GetCustomerChanges(Customer obj) {
            var propertiesMapping = new Dictionary<string, object> {
                { nameof(Customer.FirstName), obj.FirstName },
                { nameof(Customer.LastName), obj.LastName },
            };
            return propertiesMapping;
        }
        public void Dispose() {
            if (instantFeedbackSource != null) {
                instantFeedbackSource.ResolveSession -= InstantFeedbackSource_ResolveSession;
                instantFeedbackSource.DismissSession -= InstantFeedbackSource_DismissSession;
                instantFeedbackSource.Dispose();
            }
        }
    }
    

    Bind Blazor Grid to Data using XPO

    Limitations

    Note the following Grid-related limitations when using Server Mode and Instant Feedback data sources:

    Instant Feedback data sources also have the following specifics: