Problem with adding records

  1. #1

    Problem with adding records

    Hello

    here is sample code
    
    <%@ Page Language="C#" %>
    
    <%@ Import Namespace="System.Data" %>
    <%@ Import Namespace="System.Xml.Xsl" %>
    <%@ Import Namespace="System.Xml" %>
    <%@ Import Namespace="System.Linq" %>
    
    <script runat="server">
    	
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
    </head>
    <body>
    <script>
    	var index = -1;
    	function setupStoreUsingAdd() {
    
    	}
    
    
    
    	function addRecordsToStore() {
    		var store = <%= GridPanel1.ClientID %>.store;
    		var data = {
    			Id: index,
    			Text: 'Text' + index--
    		};
    		store.add([data]);
    	}
    
    	function addRecordsUsingLoadData() {
    		var store = <%= GridPanel1.ClientID %>.store;
    		var data = {
    			Id: index,
    			Text: 'Text' + index--
    		};
    		store.loadData([data],true);
    	}
    
    	Ext.onReady(function () {
    		var ret = [];
    		var store = <%= GridPanel1.ClientID %>.store;
    		for (var i = 0; i < 12; i++) {
    			ret.push({
    				Id: i,
    				Text: 'Text' + i
    			});
    		}
    		store.loadData(ret);
    	});
    
    
    </script>
        <form runat="server">
            <ext:ResourceManager runat="server" Namespace="" StateProvider="Cookie" />
    
    		
    		<ext:Button runat="server"  Text="Add records using Store" OnClientClick="addRecordsToStore()"></ext:Button>
    	    <ext:Button runat="server"  Text="Add records using LoadData" OnClientClick="addRecordsUsingLoadData()"></ext:Button>
    		
    	    <ext:Store runat="server" ID="Store1"
    		    PageSize="10" AutoLoad="False">
    		    <Model>
    			    <ext:Model runat="server">
    		           <Fields>
    			           <ext:ModelField Name="Id"/>
    			           <ext:ModelField Name="Text"/>
    		           </Fields>
    			    </ext:Model>
    		    </Model>
    	    </ext:Store>
    		
    	    <ext:GridPanel
    		    id="GridPanel1"
    		    runat="server"
    		    StoreID="Store1"
    		    Title="DataTable Grid"
    		    Stateful="True"
    		    StateID="gridState"
    		    
    		    >
    		    <ColumnModel runat="server">
    			    <Columns>
    				    <ext:Column runat="server" Text="Id" DataIndex="Id" Flex="1"/>
    			
    				 
    			    </Columns>
    		    </ColumnModel>
              
    		    <BottomBar>
    			    <ext:PagingToolbar runat="server" StoreID="Store1" />
    		    </BottomBar>
    	    </ext:GridPanel>
        </form>
    </body>
    </html>
    The problem here is reproducible if I navigate to the second page of the grid ( paging toolbar)
    1) if after navigating to second page "Add records using Store" is used repeatelly, then on the page will be more then 10 records
    2) if "Add records using LoadData" is used after navigating to second page, all data from first page will be lost

    Thanks
    Jiri
  2. #2
    Hello, @jirihost!

    This subject has been discussed in this thread: How to sync-up paging after inserting a Store record?

    But, as you went all the way down to a nicely reproducible test case, and based in that thread above, I could come up with a quick solution for your first approach. There's always room for improvement, but I believe with the changes you'd have everything to make it work the way you need the most:

    So, just change your addRecordsToStore() function to reload the page right after the record is added, to keep the amount of records displayed in the page in check, and also handle edge cases like new pages being necessary to display all records. And to avoid flickers in the process, we pause layout updates until the record is in place and page reloaded:

    function addRecordsToStore() {
    	var grid = <%= GridPanel1.ClientID %>;
    	var store = grid.store;
    	var data = {
    		Id: index,
    		Text: 'Text' + index--
    	};
    	grid.suspendLayouts();
    	store.add([data]);
    	store.loadPage(store.currentPage);
    	grid.resumeLayouts();
    }
    Perhaps, if anything, you might want to switch to the last page (where records are added) or, if sorted, you'd need to do some extra work to tell where the records should pop up once added, and switch to the correct page where the record is shown. But I believe that would depend on your actual requirements for the grid. (hint: store.findPage(record))

    The second approach you have in addRecordsUsingLoadData() don't look right to me, in the very shallow look I gave it. By the letter, it makes complete sense, but I believe the store.loadData() method is simply not optimized for paging stores and behaved unreliably in my tests.

    Please give a try to the reviewed first approach and let us know if you have a specific need to use store.loadData(), we may need to come up with an override to make it properly work with Ext.data.PagingStore kind of stores (any paging grid automatically has their store set to this as it adds required code for paging grid to work in Ext.NET context).

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    Ok thanks
    I'm trying to understand this a little bit more and narrowing sample little bit:

    use case
    - there are many records in grid ( 100+)
    - user is on second or third page
    - user add many records to grid (100+ , teoretically couple tousands)

    expected behavior
    - reocrds are quickly added to the right position ( sorting works)

    I still have two approaches, for me the loadData works little better

    Hovewer what I found interesting, the loadData version performs much better ( like few miliseconds for loadData method, 10-20 seconds for store adding)

    <%@ Page Language="C#" %>
    
    <%@ Import Namespace="System.Data" %>
    <%@ Import Namespace="System.Xml.Xsl" %>
    <%@ Import Namespace="System.Xml" %>
    <%@ Import Namespace="System.Linq" %>
    
    <script runat="server">
    	
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
    </head>
    <body>
    <script>
    
        var numberOfRecordsToAdd = 500;
        function setupStoreUsingAdd() {
    
        }
    
    
    
        function addRecordsToStore() {
            var grid = <%= GridPanel1.ClientID %>;
            var store = <%= GridPanel1.ClientID %>.store;
    		var newData = [];
    
    		for (var i = 0; i < numberOfRecordsToAdd; i++) {
    			newData.push({
    				Id: i,
    				Text: 'New Data' + i
    			});
    		}
    
    		grid.suspendLayouts();
    		store.add(newData);
    		store.loadPage(store.currentPage);
    		grid.resumeLayouts();
    	}
    
    	function addRecordsUsingLoadData() {
    		var grid = <%= GridPanel1.ClientID %>;
    		var store = <%= GridPanel1.ClientID %>.store;
    
    		var data = [];
    
    		// add existing data first
    		store.each(function (record) {
    			data.push(record.data);
    		}, this, { filtered: true });
    
    		// add new data
    
    		for (var i = 0; i < numberOfRecordsToAdd; i++) {
    			data.push({
    				Id: i,
    				Text: 'New Data' + i
    			});
    		}
    
    
    		store.loadData(data);
    	}
    
    	Ext.onReady(function () {
    		var ret = [];
    		var store = <%= GridPanel1.ClientID %>.store;
            ret.push({
                Id: -1,
                Text: 'A record'
            });
    
            for (var i = 0; i < numberOfRecordsToAdd; i++) {
                ret.push({
                    Id: i,
                    Text: 'Text' + i
                });
            }
    
            ret.push({
                Id: -2,
                Text: 'Z record'
            });
            store.loadPage(2);
    
            store.loadData(ret);
        });
    
    
    </script>
        <form runat="server">
            <ext:ResourceManager runat="server" Namespace="" StateProvider="Cookie" />
    
    		
    		<ext:Button runat="server"  Text="Add records using Store" OnClientClick="addRecordsToStore()"></ext:Button>
    	    <ext:Button runat="server"  Text="Add records using LoadData" OnClientClick="addRecordsUsingLoadData()"></ext:Button>
    		
    	   
    		
    	    <ext:GridPanel
    		    id="GridPanel1"
    		    runat="server"
    		    
    		    Title="DataTable Grid"
    		    Stateful="True"
    		    StateID="gridState"
    		    
    		    >
    			<Store>
    				<ext:Store runat="server" ID="Store1"
    				           PageSize="10" AutoLoad="true" RemoteSort="false" RemotePaging="false">
    					<Sorters>
    						<ext:DataSorter Property="Text"/>
    					</Sorters>
    					<Model>
    						<ext:Model runat="server">
    							<Fields>
    								<ext:ModelField Name="Id"/>
    								<ext:ModelField Name="Text"/>
    								<ext:ModelField Name="VersionStamp" />
    								</Fields>
    						</ext:Model>
    					</Model>
    				</ext:Store>
    			</Store>
    		    <ColumnModel runat="server">
    			    <Columns>
    				    <ext:Column runat="server" Text="Id" DataIndex="Id" Flex="1"/>
    				    <ext:ComponentColumn runat="server" Text="Text" DataIndex="Text" Flex="1" Editor="True">
    						<Component>
    							<ext:TextField runat="server"></ext:TextField>
    						</Component>
    				    </ext:ComponentColumn>
    					
    				 
    			    </Columns>
    		    </ColumnModel>
    			
    		    <SelectionModel>
    			    <ext:CheckboxSelectionModel runat="server" Mode="Multi">
    			    </ext:CheckboxSelectionModel>
    		    </SelectionModel>
    		    <BottomBar>
    			    <ext:PagingToolbar runat="server" StoreID="Store1" />
    		    </BottomBar>
    	    </ext:GridPanel>
        </form>
    </body>
    </html>
  4. #4
    Hello again, Jiri!

    For this amount of data you're handling, I believe it would be best to use remote paging, then bulk-upload the 1000s records uploaded at once. Then you can just fetch the desired page on server and (if the code to return the portion of records is correct) it should simply load the page right.

    But as you pointed, when doing bulk insertions, it's better to fully reload the store than iterate the batch of elements.

    Probably if you also support adding, say, <10 records at a time, best would be an hybrid solution, resorting to loadData() when your code deems it is a bulk load, and add() when there are just a few records.

    The problem I noted with loadData() in the previous post involved loadData(records, true), that is, when it is meant to append data to the grid. It was erratic. By pulling the full data set yourself and calling the method to do a full reload, I believe you are doing a cumbersome task for when just a few records are added, but the right choice when a large number of records are added at once.

    In the end, are both approaches working for you or is there something that still doesn't work? If the concern is just performance, the hybrid approach could be better if you need to affor both pontual and bulk inserts.
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. Problem with removing records from grid
    By jirihost in forum 5.x Legacy Premium Help
    Replies: 6
    Last Post: Sep 24, 2021, 1:33 AM
  2. Replies: 2
    Last Post: Oct 09, 2018, 9:06 PM
  3. [CLOSED] Adding Records in a Grid not updates the Paging informaton properly
    By speedstepmem3 in forum 1.x Legacy Premium Help
    Replies: 5
    Last Post: Nov 02, 2011, 11:50 AM
  4. Add Records dynamically, Save problem
    By zhangsir199 in forum 1.x Help
    Replies: 12
    Last Post: Mar 28, 2011, 8:45 PM
  5. Problem after update records
    By Argons in forum 1.x Help
    Replies: 1
    Last Post: Aug 06, 2009, 1:36 PM

Posting Permissions