{"id":7223,"date":"2005-04-14T22:41:00","date_gmt":"2005-04-14T22:41:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2005\/04\/14\/tableadapters-and-object-binding-bridging-the-gap\/"},"modified":"2024-07-05T14:57:51","modified_gmt":"2024-07-05T21:57:51","slug":"tableadapters-and-object-binding-bridging-the-gap","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/tableadapters-and-object-binding-bridging-the-gap\/","title":{"rendered":"TableAdapters and Object Binding &#8211; Bridging the gap"},"content":{"rendered":"<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Tahoma\">I&rsquo;ve been working on getting an article out on leveraging the data design time features, and the new object binding features we&rsquo;ve added in Whidbey.<span>&nbsp; <\/span>We&rsquo;ve been busy getting Beta 2 done, so I haven&rsquo;t finished it yet, but here&rsquo;s a rough draft of the full article.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">TableAdapters and Object Binding<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">In Whidbey we&rsquo;ve done a lot of work to enable design time support for object based data binding.<span>&nbsp; <\/span>This leaves the question of how to load and save custom objects.<span>&nbsp; <\/span>How do developers get the rich functionality of DataSet but using their own object model?<span>&nbsp; <\/span>In this article I&rsquo;ll describe some common infrastructure for building a set of base classes to enable round tripping your objects to\/from the database.<\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Loading and Saving Objects<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">The first question is usually how to load my objects.<span>&nbsp; <\/span>Should I use DataReaders or can I leverage the new TableAdapter features?<span>&nbsp; <\/span>I still need to get actual perf numbers, but a key issue to consider is the productivity of the development team, not just the raw performance of the application.<span>&nbsp; <\/span>While you can certainly use DataReaders to load your objects, you&rsquo;ll incur extra responsibilities for managing the state of the DataReader and the untyped nature of the parameters and the results of the DataReader.<span>&nbsp; <\/span>By using the TableAdapters you can dramatically increase your development and stabilization phase productivity by leveraging compile time verification for column changes or additions.<\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Hydrating objects<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">One of the key features we&rsquo;ve added to TableAdapters is something we refer to as DBDirect methods.<span>&nbsp; <\/span>By default TableAdapters generate <b>Get<\/b> methods as well as <b>Fill<\/b> methods.<span>&nbsp; <\/span>The key difference is the <b>Fill<\/b> method will fill an existing DataSet or DataTable.<span>&nbsp; <\/span>The <b>Get<\/b> methods will return a new DataTable for your particular query.<span>&nbsp; <\/span>We can then use the Get method to iterate through the DataTable and create custom objects.<span>&nbsp; <\/span>Yes, we&rsquo;re creating a DataTable then tossing it out, but let&rsquo;s look at the code we can easily write.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Tahoma\">Using the Data Sources Window add a new Database Data Source to the Northwind database.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Tahoma\">To simplify this sample choose the Employees table but only choose EmployeeID, FirstName, LastName and HireDate.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">Click finish to create the NorthwindDataSet which includes the DataTables and TableAdapters<\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Finding employees by name<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">We&rsquo;ll want to add an additional query to the EmployeesTableAdapter to find employees by their last name.<span>&nbsp; <\/span>For the purposes of this article we&rsquo;re going to simplify things a little bit and remove the concurrency checks and the refresh options.<span>&nbsp; <\/span>To change this behavior, select the TableAdapter in the DataSet designer and choose Configure.<span>&nbsp; <\/span>Choose the Advanced Options button and uncheck the checkboxes for <b>Use optimistic concurrency<\/b> and <b>Refresh the data table<\/b>.<span>&nbsp; <\/span>Click finish to close the wizard.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">The next thing we&rsquo;ll do is add our additional query.<span>&nbsp; <\/span>On the EmployeeTableAdapter select the Add Query task on the context menu.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">To leverage sprocs, choose the Create new stored procedure as the command type and then choose SELECT which returns rows.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">Enter the following query:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">SELECT EmployeeID, LastName, FirstName, HireDate FROM dbo.Employees<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">WHERE LastName LIKE @lastName + &#8216;%&#8217;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">Click next and name the stored procedure Employees#GetByLastName<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">On the choose the methods to generate step, name the Fill method name: FillByLastName and the Get method GetByLastName then click finish.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">Close the DataSet designer.<\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Employee Entity<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">Next we&rsquo;ll create an Employee class that represents our Employee Object.<span>&nbsp; <\/span>It will be a simple class that just caries the payload for a specific employee.<span>&nbsp; <\/span>Later on we&rsquo;ll add some change tracking\/IsDirty and validation logic.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>&#8221;&#8217; <\/span><span>&lt;summary&gt;<\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&#8221;&#8217; Represents an employee of the company<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>&#8221;&#8217; <\/span><span>&lt;\/summary&gt; <\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>Public<\/span><span> <span>Class<\/span> Employee <\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">#<span>Region<\/span> <span>&#8221; Backing Fields &#8220;<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> _employeeId <span>As<\/span> <span>Integer<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> _lastName <span>As<\/span> <span>String<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> _firstName <span>As<\/span> <span>String<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> _hireDate <span>As<\/span> Nullable(<span>Of<\/span> <span>Date<\/span>)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">#<span>End<\/span> <span>Region<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Property<\/span> EmployeeId() <span>As<\/span> <span>Integer<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> _employeeId<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Set<\/span>(<span>ByVal<\/span> value <span>As<\/span> <span>Integer<\/span>)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_employeeId = value<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Set<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Property<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Property<\/span> LastName() <span>As<\/span> <span>String<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> _lastName<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Set<\/span>(<span>ByVal<\/span> value <span>As<\/span> <span>String<\/span>)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_lastName = value<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Set<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Property<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Property<\/span> FirstName() <span>As<\/span> <span>String<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> _firstName<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Set<\/span>(<span>ByVal<\/span> value <span>As<\/span> <span>String<\/span>)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_firstName = value<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Set<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp; <\/span><span>&nbsp;<\/span><span>End<\/span> <span>Property<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>ReadOnly<\/span> <span>Property<\/span> FullName() <span>As<\/span> <span>String<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> _firstName &amp; <span>&#8221; &#8220;<\/span> &amp; _lastName<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Property<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Property<\/span> HireDate() <span>As<\/span> Nullable(<span>Of<\/span> <span>Date<\/span>)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> _hireDate<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;<\/span><span>End<\/span> <span>Get<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Set<\/span>(<span>ByVal<\/span> value <span>As<\/span> Nullable(<span>Of<\/span> <span>Date<\/span>))<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_hireDate = value<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Set<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Property<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>End<\/span><span> <span>Class<\/p>\n<p><\/span><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Employee Factory<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">We now need a factory class to load and create a collection of employees.<span>&nbsp; <\/span>However, we&rsquo;ll need to add some functionality to our collection of employees so we&rsquo;ll create an EmployeeList collection.<span>&nbsp; <\/span>For now, it will be pretty simple, but later on we&rsquo;ll add some functionality for GetChanges.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>Public<\/span><span> <span>Class<\/span> EmployeeList<\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Inherits<\/span> System.ComponentModel.BindingList(<span>Of<\/span> Employee)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>End<\/span><span> <span>Class<\/p>\n<p><\/span><\/span><\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Tahoma\" size=\"2\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">To create the Factory we&rsquo;ll use the following code:<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>Public<\/span><span> <span>Class<\/span> EmployeeFactory<\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; sinlge instance of the TableAdapter to be used by the Factory<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Shared<\/span> _employeesTableAdapter <span>As<\/span> NorthwindDataSetTableAdapters.EmployeesTableAdapter<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Shared<\/span> <span>Sub<\/span> <span>New<\/span>()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_employeesTableAdapter = <span>New<\/span> NorthwindDataSetTableAdapters.EmployeesTableAdapter()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; <\/span><span>&lt;summary&gt;<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; Gets all employees for a given last name<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; <\/span><span>&lt;\/summary&gt;<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Shared<\/span> <span>Function<\/span> GetEmployeesByLastName(<span>ByVal<\/span> lastName <span>As<\/span> <span>String<\/span>) <span>As<\/span> EmployeeList<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> employeeList <span>As<\/span> <span>New<\/span> EmployeeList()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> employeesDataTable <span>As<\/span> NorthwindDataSet.EmployeesDataTable<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>employeesDataTable = _employeesTableAdapter.GetByLastName(lastName)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> ConvertRowsToList(employeesDataTable)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; <\/span><span>&lt;summary&gt;<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; Gets all employees<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; <\/span><span>&lt;\/summary&gt;<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Shared<\/span> <span>Function<\/span> GetAllEmployees() <span>As<\/span> EmployeeList<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> employeesDataTable <span>As<\/span> NorthwindDataSet.EmployeesDataTable<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>employeesDataTable = _employeesTableAdapter.GetData()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> ConvertRowsToList(employeesDataTable)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; <\/span><span>&lt;summary&gt;<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; Internal method for converting rows to employee entities<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8221;&#8217; <\/span><span>&lt;\/summary&gt;<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Shared<\/span> <span>Function<\/span> ConvertRowsToList(<span>ByVal<\/span> employeesDataTable <span>As<\/span> NorthwindDataSet.EmployeesDataTable) <span>As<\/span> EmployeeList<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> employeeList <span>As<\/span> <span>New<\/span> EmployeeList()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>For<\/span> <span>Each<\/span> employeeRow <span>As<\/span> NorthwindDataSet.EmployeesRow <span>In<\/span> employeesDataTable<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;<\/span><span>Dim<\/span> newEmployee <span>As<\/span> <span>New<\/span> Employee()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>With<\/span> newEmployee<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; use the typed row as the accessor for each column<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>.EmployeeId = employeeRow.EmployeeID<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>.FirstName = employeeRow.FirstName<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>.LastName = employeeRow.LastName<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Becuase HireDate<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> employeeRow.IsHireDateNull <span>Then<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>.HireDate = <span>Nothing<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Else<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>.HireDate = employeeRow.HireDate<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>With<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>employeeList.Add(newEmployee)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Next<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> employeeList<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/p>\n<p><\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>End<\/span><span> <span>Class<\/p>\n<p><\/span><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">In the above code you&rsquo;ll see that I used the typed EmployeeRow to get the specific columns.<span>&nbsp; <\/span>In addition I was able to leverage the typed parameters on the TableAdapter for the FillByLastName.<span>&nbsp; <\/span>This is just an example of where the developer gets some productivity gains.<span>&nbsp; <\/span>If the column names change in the DataSet, or the parameters change on the TableAdapters, VS will generate compile time errors.<span>&nbsp; <\/span>This means you don&rsquo;t have to run your app just to find out its broken.<span>&nbsp; <\/span>You&rsquo;ll also notice that I had to check if the HireDate was null.<span>&nbsp; <\/span>This is the one hole we still have in our designtime null support.<span>&nbsp; <\/span>We weren&rsquo;t able to get the nullable columns done on the typed DataTable, although the TableAdapters are fully null aware. <\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Loading a form<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Tahoma\">To test out our progress, let&rsquo;s do a little Drag Once DataBinding.<span>&nbsp; <\/span>To keep the productivity going, I&rsquo;m going to leverage the object binding features of the Data Sources Window.<span>&nbsp; <\/span>Be sure to build your project to make sure all the types are compiled.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">Using the Data Sources Window choose the object data source type a\nnd select your employee class. Notice that any XML comments you put on the class are displayed below the list.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Tahoma\">If your employee object is in the same assembly as the dataset and the form you&rsquo;ll notice the NorthwindDataSet is also displayed in the Data Sources Window, however we&rsquo;re going to use the employee object we just created.<span>&nbsp; <\/span>From the Data Sources Window drag this employee object to your form.<span>&nbsp; <\/span>This will create an EmployeeDataGridView bound to a BindingSource named EmployeeBindingSource.<span>&nbsp; <\/span>If you look at the .designer file you&rsquo;ll see EmployeeBindingSource.DataSource property is set to <\/font><span>GetType<\/span><span>(Employee)<\/span><font face=\"Tahoma\"> This tells the BindingSource to emit the &ldquo;shape&rdquo; of the employee object to controls bound to the BindingSource.<span>&nbsp; <\/span>This is why the DataGridView shows the columns for the employee object.<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">The next step is to actually get some data.<span>&nbsp; <\/span>Double click on the form to get the form load event.<span>&nbsp; <\/span>Add the following code:<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>Me<\/span><span>.EmployeeBindingSource.DataSource = EmployeeFactory.GetAllEmployees()<\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">To make it more interesting, add a textbox and a button to the form and add the following code to the button.click event:<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>Me<\/span><span>.EmployeeBindingSource.DataSource = EmployeeFactory.GetEmployeesByLastName(<span>Me<\/span>.TextBox1.Text.Trim)<\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">We now have the basic model established.<span>&nbsp; <\/span>We can load entity objects with a factory pattern using the data design time features, and we have full control over our entity objects.<span>&nbsp; <\/span>The next step is to save the objects.<span>&nbsp; <\/span>This brings up some interesting challenges that the DataSet solves, but I&rsquo;ll demonstrate how to get the basic functionality with your own objects.<\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Batch of Individual Updates<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Tahoma\">One of the first things to consider is whether you plan to support batch updates.<span>&nbsp; <\/span>By batch I mean the user can change several rows of data before committing the changes back to the database.<span>&nbsp; <\/span>This may involve listing several phone numbers for a contact, or the creation of a new order with several line items.<span>&nbsp; <\/span>Once you go beyond a single row things get a little more complicated.<span>&nbsp; <\/span>We need to track whether the end user added, deleted or modified the given row.<span>&nbsp; <\/span>So which is better, direct to the database &ndash; AKA MS Access Style?<span>&nbsp; <\/span>Or batch?<span>&nbsp; <\/span>Well, as most technical decisions, it depends.<span>&nbsp; <\/span>Certainly when you&rsquo;re working on an isolated app with a single user database, the direct to database style works well and definitely reduces the complexity.<span>&nbsp; <\/span>However, when working in any shared environment, particularly mission critical systems where multiple people are reading and writing to the database at a given time it&rsquo;s important to only save &ldquo;completed&rdquo; information.<span>&nbsp; <\/span>For instance let&rsquo;s say we&rsquo;re creating an order for a customer that just called in.<span>&nbsp; <\/span>The customer wants to get some pricing and check inventory on some items.<span>&nbsp; <\/span>They don&rsquo;t want to give their personal information until they know the company has the items at the price they want to pay.<span>&nbsp; <\/span>The sales rep starts to create a new order.<span>&nbsp; <\/span>They enter a bunch of line items that the customer was asking about.<span>&nbsp; <\/span>At this point the sales rep doesn&rsquo;t have enough information to fill out the Order Header record so we can&rsquo;t save it back to the database.<span>&nbsp; <\/span>And should we?<span>&nbsp; <\/span>So far this is just a set of scratch notes.<span>&nbsp; <\/span>If the customer hangs up, it&rsquo;s cumbersome to have to clean up the database.<span>&nbsp; <\/span>There are other strategies such as scratch tables, and good old post-it notes.<span>&nbsp; <\/span>However, if the customer decides to place the order the sales rep shouldn&rsquo;t have to copy that information into an order.<span>&nbsp; <\/span>It really comes down to whether your database contains information that the company will act upon, or is it a place to store state and transient data?<span>&nbsp; <\/span>In general developers tend write information back to the database because they find it easier to read\/write to the database rather then maintain their own in-memory cache.<span>&nbsp; <\/span>For websites this may actually be required in order to manage a true stateless environment.<span>&nbsp; <\/span>However, even in web scenarios its best to use an isolated database for maintaining your state.<span>&nbsp; <\/span>As the end user completes their operation, the data is then moved to the main database that runs the business.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">In order to minimize the activity with the database and get the greatest scalability, its best to leverage the power of the desktop and manage updates in batches.<\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">Self aware objects, or entities and factories<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">There are two distinct patterns the have surfaced.<span>&nbsp; <\/span>One is the self aware model.<span>&nbsp; <\/span>In this case the employee class would have save and load methods.<span>&nbsp; <\/span>The problem with this model is each employee object has to maintain a lot more common functionality, such as the data access code, or a web service to pass its self back to.<span>&nbsp; <\/span>This also means it&rsquo;s harder to batch operations such as a single call to a web service, database, or to incorporate a transaction.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Tahoma\">The other model is the entity model where each object maintains a minimal set of information to represent its self.<span>&nbsp; <\/span>It&rsquo;s also nice to incorporate basic validation logic so the end user receives immediate feedback on the validity of their data.<span>&nbsp; <\/span>In order to load or save these objects a factory pattern is used.<span>&nbsp; <\/span>A call is made to a factory and it returns a collection of entity objects.<span>&nbsp; <\/span>In order to save the objects, the collection is passed back to the factory and the factory saves the changes.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><b><span><font face=\"Tahoma\">What changed?<\/p>\n<p><\/font><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Tahoma\" size=\"2\">In batch operations we need to have each entity track its state is.<span>&nbsp; <\/span>At first glance you might thing an IsDirty Boolean property.<span>&nbsp; <\/span>But we really need to track Inserted, Modified and Deleted.<span>&nbsp; <\/span>This can be described with a simple enum that you can add to your project.<\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&lt;Flags()&gt; _<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>Public<\/span><span> <span>Enum<\/span> ObjectState<\/p>\n<p><\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>Unchanged<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font><\/font><\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&rsquo;ve been working on getting an article out on leveraging the data design time features, and the new object binding features we&rsquo;ve added in Whidbey.&nbsp; We&rsquo;ve been busy getting Beta 2 done, so I haven&rsquo;t finished it yet, but here&rsquo;s a rough draft of the full article.&nbsp; TableAdapters and Object Binding In Whidbey we&rsquo;ve done [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[192,195],"tags":[],"class_list":["post-7223","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-visual-basic"],"acf":[],"blog_post_summary":"<p>I&rsquo;ve been working on getting an article out on leveraging the data design time features, and the new object binding features we&rsquo;ve added in Whidbey.&nbsp; We&rsquo;ve been busy getting Beta 2 done, so I haven&rsquo;t finished it yet, but here&rsquo;s a rough draft of the full article.&nbsp; TableAdapters and Object Binding In Whidbey we&rsquo;ve done [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/7223","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=7223"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/7223\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=7223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=7223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=7223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}