asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search








Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Creating a Data Access Layer for Paging in SQL Server 2005
By David Beahm
Rating: 4.2 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    In my previous article, Paging in SQL Server 2005, I demonstrated how to support paging the results of a SQL query inside of a stored procedure. In this two-part article, I will tie that logic to an ASP.NET page with a GridView and DetailsView to demonstrate an efficient way to incorporate paging and updating through an ObjectDataSource. Along the way we will use the Class Diagram tool and the Web Application Project template (added to Visual Studio 2005 by Service Pack 1), although you are free to use methods you are more comfortable with.

    Background

    Visual Studio 2005 introduced a number of tools that allow web developers to create dynamic web pages more easily than ever. The GridView encapsulates most of the functionality needed for displaying and editing tabular data efficiently, and can bind to several types of data sources. The DetailsView is a sibling to the GridView, supporting most of the same functionality but displaying a single record at a time. While these controls can bind to databases through simple DataSets and SqlDataSources, the ObjectDataSource control provides a more clearly defined, more sophisticated -- but potentially more complicated -- connection. For developers looking to model their SQL data within the application through custom classes, the ObjectDataSource allows them to bind their strongly-typed classes to user controls and add a discrete Business Logic Layer to ensure user interactions follow defined rules of behavior.

    The Database Layer

    The first order of business is to create a database to work with; the examples below were created in a database called DALdemo, but you can change the connection string to whatever name you choose. Once you have done this, the following SQL statement will create a simple table to work with:

    CREATE TABLE [dbo].[Person]
    (
        [PersonID] [int] IDENTITY(1,1) NOT NULL,
        [FirstName] [nvarchar](50) NOT NULL,
        [MiddleName] [nvarchar](50) NULL,
        [LastName] [nvarchar](50) NOT NULL,
        [Height] [decimal](5, 2) NULL,
    CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
    (
        [PersonID] ASC
    ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
        ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    To populate the table with some preliminary test data, execute the following SQL statements:

    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Frank', 'Edward', 'Holiday', 62.38)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Nancy', 'Estelle', 'Walkafeller', 52.81)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Stewart', 'R.', 'Garvey', 61)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Jeff', 'A.', 'Walker', 66.43)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Walter', 'Albert', 'Johnson', 65.66)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Barbara', 'Connie', 'Jones', 65.38)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('William', '', 'Smith', 59.68)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Gillian', 'Kay', 'Krissinger', 62.43)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Sam', '', 'Stuart', 65.67)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Richard', 'G.', 'Harding', 63.98)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Laura', 'Edward', 'Kinsley', 70.56)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Frank', 'Quincy', 'George', 67.31)
    INSERT INTO Person (FirstName, MiddleName, LastName, Height) VALUES ('Frank', 'P.', 'Williams', 62.99)

    We will use the following stored procedure to query this table, which incorporates SQL paging logic and uses a ReturnValue parameter to pass back the total number of records.

    CREATE PROCEDURE [dbo].[utilPAGE]
        @datasrc     nvarchar(200)
        ,@orderBy    nvarchar(200)
        ,@startPage  int = 1
        ,@pageSize   int = NULL
        ,@fieldlist  nvarchar(200) = '*'
        ,@filter     nvarchar(200) = ''
    AS
        SET NOCOUNT ON
        DECLARE
            @STMT nvarchar(max)            -- SQL to execute
            ,@recct int                    -- total # of records
        SET @recct = -1
        IF LTRIM(RTRIM(@filter)) = '' SET @filter = '1 = 1'
        IF @pageSize IS NULL BEGIN
            SET @STMT = ' SELECT   ' + @fieldlist +
                        ' FROM     ' + @datasrc +
                        ' WHERE    ' + @filter +
                        ' ORDER BY ' + @orderBy
            EXEC (@STMT)                   -- return requested records
        END ELSE BEGIN
            SET @STMT = ' SELECT  @recct = COUNT(*)
                          FROM    ' + @datasrc +
                        ' WHERE   ' + @filter
            EXEC sp_executeSQL @STMT, @params = N'@recct INT OUTPUT', @recct = @recct OUTPUT

            DECLARE
                @lbound int,
                @ubound int

            IF @startPage < 1 SET @startPage = 1
            IF @pageSize < 0 SET @pageSize = @pageSize * -1
            IF @pageSize < 1 SET @pageSize = 1
            SET @lbound = ((@startPage - 1) * @pageSize)
            SET @ubound = @lbound + @pageSize + 1
            IF @lbound >= @recct BEGIN
                SET @ubound = @recct + 1
                SET @lbound = @ubound - (@pageSize + 1)   -- return last page of records
            END
            SET @STMT = ' SELECT  ' + @fieldlist +
                        ' FROM (
                          SELECT ROW_NUMBER() OVER(ORDER BY ' + @orderBy + ') AS row, *
                          FROM    ' + @datasrc +
                        ' WHERE   ' + @filter +
                        ' ) AS tbl
                          WHERE  row > ' + CONVERT(varchar(9), @lbound) +
                        ' AND    row < ' + CONVERT(varchar(9), @ubound) + ' '
            EXEC (@STMT)                   -- return requested records
        END
        RETURN @recct

    We will use the PersonSET stored procedure to handle updates to the Person table. PersonSET handles both inserts and updates, with items being inserted if the @ID parameter is less than one:

    CREATE PROCEDURE [dbo].[PersonSET]
    (
         @ID int = -1
        ,@FirstName nvarchar(50)
        ,@MiddleName nvarchar(50)
        ,@LastName nvarchar(50)
        ,@Height decimal(5, 2)
    )
    AS
        SET NOCOUNT ON
        BEGIN TRY
            BEGIN TRANSACTION
            IF @ID > 0 BEGIN
                UPDATE  Person
                SET     FirstName = @FirstName,
                        MiddleName = @MiddleName,
                        LastName = @LastName,
                        Height = @Height
                WHERE   PersonID = @ID;
            END ELSE BEGIN
                INSERT INTO Person (FirstName, MiddleName, LastName, Height)
                VALUES             (@FirstName, @MiddleName, @LastName, @Height);
                SET @ID = SCOPE_IDENTITY()
            END
            COMMIT TRANSACTION
            RETURN @ID
        END TRY
        BEGIN CATCH
            DECLARE
                @ERNUM int
            SELECT @ERNUM = ERROR_NUMBER()
            ROLLBACK TRANSACTION
            IF @ERNUM > 0 SET @ERNUM = -@ERNUM
            RETURN @ERNUM
        END CATCH

    PersonDELETE removes one record at a time from Person, based on the ID field:

    CREATE PROCEDURE PersonDELETE
    (
        @ID int = 5
    )
    AS
        SET NOCOUNT ON
        DELETE FROM Person
        WHERE       PersonID = @ID

    The Data Object Layer

    The next step is to create a new C# ASP.NET Web Application called WebApp1 in Visual Studio. As shown in Illustration 1, enable the option Create directory for solution and set the Solution Name to 15Seconds. This will allow us to work with multiple projects simultaneously.


    Illustration 1: Creating the Web Project and Solution

    To create the second project, select File | New | Project and create a new C# Class library called Library1. Be sure to change the default setting from Create new Solution to Add to Solution, as shown in Illustration 2.


    Illustration 2: Creating the class project within the solution

    Feel free to close and delete the Class1.cs file created automatically by Visual Studio, as we will not be using it. To create the class we do need, right-click on the Library1 project in the Solution Explorer, select Add | Class, and create a class named PersonEntity.cs. The quickest way to fill in the class is with the Class Editor; in the Solution Explorer, right-click on PersonEntity.cs and select View Class Diagram.

    The class needs internal data members for holding values, and we will follow the common practice of prefixing an underscore to their names to avoid confusion later. To create these, click on the <add field> text, type _ID, and press tab. Set Type to be int, and set modifier to private. Add the next three fields, _FirstName, _MiddleName, and _LastName, all with Type set to string. Lastly, add field _Height with Type set to double.

    The class needs accessor (set/get) methods so other classes can modify these internal values. To create these, click on the <add property> text, type ID, and press tab. Set Type to be int, and set modifier to public. Add the next three properties, called FirstName, MiddleName, and LastName, all with Type set to string. Lastly, add property Height with Type set to double.

    At this point, your class diagram should resemble Illustration 3.


    Illustration 3: Creating the PersonEntity skeleton with the Class Diagram tool

    Right-click on ClassDiagram1.cd and select Rename; change the name to diaPersonEntity.cd. Click on the PersonEntity.cs* tab to see what has been happening in the background. The fields we added will show up as private data members:

        private int _ID;
        private string _FirstName;
        private string _MiddleName;
        private string _LastName;
        private double _Height;

    The properties we added show up as public get/set methods. The ID property is:

        public int ID
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

    We need to wire the fields and properties together, so that when someone refers to a class property, the relevant field is used. Change the ID property to:

        public int ID
        {
            get
            {
                return _ID;
            }
            set
            {
                _ID = value;
            }
        }

    Making private data members with public get/set methods probably seems like a lot of extra work, but it is an important part of good design that prevents subtle bugs and supports additional functionality. If a class' internal data members are exposed, other classes may inadvertently modify the internal values without trying. Also, set/get methods allow us to ensure the values used meet any requirements we might have. If, for example, we want to ensure that _ID can only be set to values greater than zero, we can add code in the set method to ensure this:

        public int ID
        {
            get
            {
                return _ID;
            }
            set
            {
                if(value > 0)
                {
                    _ID = value;
                }
                else
                {
                    throw new Exception("ID must be greater than zero");
                }

            }
        }

    Alternatively, if we want the internal values to return an empty string when they are set to null, we can change each of the get methods for string properties to use C#'s ?? operator. This is similar to SQL Server's ISNULL() function: if the first value specified is NULL, the second value specified is used instead. This can be used as shown below:

        public string FirstName
        {
            get
            {
                return _FirstName ?? "";
            }
            set
            {
                _FirstName = value;
            }
        }

    Note that the above code isn't strictly necessary for this project; it is simply an example of things you can do if you want strict validation or other behavior within your custom class (which is the primary benefit of making custom classes). If you still aren't sold on the idea, see http://msdn2.microsoft.com/en-us/library/65zdfbdt(VS.71).aspx for a more complete explanation of the benefits.

    Since we want to access this class from another project, be sure to change the class declaration to:

    namespace Library1
    {
        public class PersonEntity
        {

    At its simplest, the PersonEntity.cs class should resemble:

    using System;

    namespace Library1
    {
        public class PersonEntity
        {
            private int _ID;
            private string _FirstName;
            private string _MiddleName;
            private string _LastName;
            public double _Height;

            public int ID
            {
                get
                {
                    return _ID;
                }
                set
                {
                    _ID = value;
                }
            }

            public string FirstName
            {
                get
                {
                    return _FirstName;
                }
                set
                {
                    _FirstName = value;
                }
            }

            public string MiddleName
            {
                get
                {
                    return _MiddleName ?? "";
                }
                set
                {
                    _MiddleName = value;
                }
            }

            public string LastName
            {
                get
                {
                    return _LastName;
                }
                set
                {
                    _LastName = value;
                }
            }

            public double Height
            {
                get
                {
                    return _Height;
                }
                set
                {
                    _Height = value;
                }
            }
        }
    }

    The Data Access Layer

    Continuing to build from the back-end data store towards the user interface, we next need to create the Data Access Layer. The Data Access Layer is a class where you define the connection between an ObjectDataSource, a custom class (in our case, PersonEntity) and the data store for instances of this class (in our case, the Person table in SQL). After you define the relevant methods in the DAL class, you will configure the ObjectDataSource object to use the correct method for each necessary function, and can then set the ASP.NET elements that will use them.

    Again, this can seem like a lot of overhead, but the extra work helps to make future maintenance easier. Instead of having specific SQL information embedded in each web page, you will define it once and be able to use it from any page that needs it. When you inevitably need to change your SQL table, you can update the class and DAL instead of editing multiple copies of the same queries throughout your web site.

    To prepare the web application, right-click on WebApp1 in Solution Explorer and select Set As StartUp Project. Next, right-click on References within the WebApp1 project and select Add Reference. Click on the Projects tab and double-click Library1 as a new reference.

    Rather than hard-coding the database connection string into our DAL class, we will store it in the web.config, where it can be modified as needed. Note that in a production environment, you should encrypt the database connection string for better security. To add your connection string, double-click the web.config file in the WebApp1 project. Modify it to have the following lines, replacing the user id and password with valid credentials and setting the data source and initial catalog with the host and database name you are using, respectively:

        <connectionStrings>
            <add name="15seconds"
                connectionString="user id=demo; pwd=demopass; data source=localhost; initial catalog=15SecondsDAL;"
                providerName="System.Data.SqlClient"
            />
        </connectionStrings>

    To create the Data Access Layer class, right-click in the WebApp1 class and select Add | Add ASP.NET Folder | App_Data (this is the standard location for DAL classes). Right-click on the App_Data folder and select Add | Class and set the name to PersonDAL.cs.

    The DAL class must support four standard SQL functions: Select, Insert, Update, and Delete. However, the PersonSET stored procedure actually handles inserts and updates automatically, so we can use the same DAL method for both of these functions. In addition to these functions, the DAL class must return the total number of instances available (in our case, the number of records in the Person table). We will store the record count value returned from the utilPAGE stored procedure, so that when a bound data control needs the total number of records for its paging interface, the DAL will return that value instead of querying the database again.

    At run-time, the ObjectDataSource settings will determine which methods to call from your DAL class for select, insert, update, delete, and count, and what information is passed into those methods. We will need to ensure that the ObjectDataSource configuration matches the DAL methods. In fact, enabling and disabling features such as sorting and paging support within the ObjectDataSource will affect which methods are called, so you may need to create overloaded versions of your DAL methods depending on the combinations of features you intend to support. In this example, however, we will include support for sorting and paging and will create methods which meet these needs.

    A straightforward implementation of the PersonDAL class is shown below. The System.ComponentModel library lets us add declarative attributes to the source code that will help the .NET compiler catch any mistakes we might make with the DAL methods, and will help when the ObjectDataSource is deciding which DAL method to use.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.Configuration;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using Library1;
    using WebApp1;

    namespace WebApp1.App_Data
    {
        [DataObject]
        public class PersonDAL
        {
            private int _count = 0;

            [DataObjectMethod(DataObjectMethodType.Select)]
            public List<PersonEntity> Select(int startRecIdx, int maxRows, String sortedBy)
            {
                List<PersonEntity> records = new List<PersonEntity>();
                SqlConnection conn = null;
                SqlDataReader dr = null;
                SqlParameter ret = null;
                try
                {
                    conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["15seconds"].ConnectionString);
                    conn.Open();
                    SqlCommand cmd = new SqlCommand("utilPAGE", conn);
                    cmd.CommandType = CommandType.StoredProcedure;
                    if(String.IsNullOrEmpty(sortedBy))
                    {
                        sortedBy = "LastName";
                    }
                    int startpg = (startRecIdx / maxRows) + 1;
                    cmd.Parameters.AddWithValue("@datasrc", "Person");
                    cmd.Parameters.AddWithValue("@orderBy", sortedBy);
                    cmd.Parameters.AddWithValue("@startPage", startpg);
                    cmd.Parameters.AddWithValue("@pageSize", maxRows);
                    ret = new SqlParameter("ReturnValue", SqlDbType.Int);
                    ret.Direction = ParameterDirection.ReturnValue;
                    cmd.Parameters.Add(ret);
                    dr = cmd.ExecuteReader();
                    while(dr.Read())
                    {
                        PersonEntity item = new PersonEntity();
                        item.ID = (int)dr["PersonID"];
                        item.FirstName = dr["FirstName"].ToString();
                        item.MiddleName = dr["MiddleName"].ToString();
                        item.LastName = dr["LastName"].ToString();
                        //item.Height = (double)(dr["Height"] ?? 0.0);
                        item.Height = Convert.ToDouble(dr["Height"].ToString());
                        records.Add(item);
                    }
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if(dr != null)
                    {
                        dr.Close();
                    }
                    if(conn != null)
                    {
                        conn.Close();
                    }
                }
                _count = Convert.ToInt32(ret.Value);
                return records;
            }

            [DataObjectMethod(DataObjectMethodType.Update)]
            public static bool Update(PersonEntity item)
            {
                bool retval = false;
                SqlConnection conn = null;
                try
                {
                    conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["15seconds"].ConnectionString);
                    conn.Open();
                    SqlCommand cmd = new SqlCommand("PersonSET", conn);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@ID", item.ID);
                    cmd.Parameters.AddWithValue("@FirstName", item.FirstName);
                    cmd.Parameters.AddWithValue("@MiddleName", item.MiddleName);
                    cmd.Parameters.AddWithValue("@LastName", item.LastName);
                    cmd.Parameters.AddWithValue("@Height", item.Height);
                    SqlParameter ret = new SqlParameter("ReturnValue", SqlDbType.Int);
                    ret.Direction = ParameterDirection.ReturnValue;
                    cmd.Parameters.Add(ret);
                    cmd.ExecuteNonQuery();
                    int result = Convert.ToInt32(ret.Value);
                    retval = result > 0;
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if(conn != null)
                    {
                    conn.Close();
                    }
                }
                return retval;
            }

            [DataObjectMethod(DataObjectMethodType.Delete)]
            public static bool Delete(PersonEntity item)
            {
                bool retval = false;
                SqlConnection conn = null;
                try
                {
                    conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["15seconds"].ConnectionString);
                    conn.Open();
                    SqlCommand cmd = new SqlCommand("PersonDELETE", conn);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@ID", item.ID);
                    SqlParameter ret = new SqlParameter("ReturnValue", SqlDbType.Int);
                    ret.Direction = ParameterDirection.ReturnValue;
                    cmd.Parameters.Add(ret);
                    cmd.ExecuteNonQuery();
                    int result = Convert.ToInt32(ret.Value);
                    retval = result > 0;
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if(conn != null)
                    {
                        conn.Close();
                    }
                }
                return retval;
            }

            public int GetRecordCount(int startRecIdx, int maxRows, string sortedBy)
            {
                return _count;
            }

            public int GetRecordCount()
            {
                return _count;
            }

        }
    }

    The Select method begins by creating an empty List collection that can hold PersonEntity objects. After declaring some ADO.NET objects, the code enters a try block. This is important, as any SQL objects used in this method need to be closed properly whether the method succeeds or fails. A connection is created based on the web.config connection string entry named 15seconds, and preparations are made for running the utilPAGE stored procedure. Because utilPAGE needs to have a non-blank orderBy argument, the LastName field is used as a default if nothing else is supplied. The parameters for table name, sort field list, starting page number, and page size are added, as is a ReturnValue parameter that will receive anything which the stored procedure explicitly sends with a return statement. The query is executed, the results are converted into new PersonEntity objects, and the PersonEntity objects are added to the List<PersonEntity> collection. The SQL objects are properly closed in the finally clause, and (because the return value can only be accessed after the SqlDataReader object is closed) the return value is stored in _count.

    The Update method receives a PersonEntity object when it is called. Because the only difference between an Insert and an Update will be the value of the ID field in this object, we will treat both the same and let the stored procedure handle the necessary logic. The Update method will largely imitate the Select method, except that the stored procedure and arguments are different and no result set will be processed. The return value will be checked to see if the update succeeded, with numbers less than one indicating an error.

    The Delete method receives a PersonEntity object when it is called, however only the ID field will be populated. (What fields are populated for this is controlled by the DataKeyNames property, which we will see later.) The Delete method is nearly identical to the Update method, except for the stored procedure and arguments. The return value will be checked to see if the delete succeeded, with numbers less than one indicating an error.

    Conclusion

    The work so far has focused on laying a foundation, and just as with building an actual foundation, there has been a lot of critical activity but little in the way of visible results. In the second part of this article, we will create an interactive web page with very little code that uses everything created so far.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Jul 21, 2005 - N-Tier Web Applications using ASP.NET 2.0 and SQL Server 2005 - Part 1
    While the .NET Framework made building ASP.NET applications easier then it had ever been in the past, .NET 2.0 builds on that foundation in order to take things to the next level. This article shows you to how to construct an N-Tier ASP.NET 2.0 Web application by leveraging the new features of ASP.NET 2.0 and SQL Server 2005.
    [Read This Article]  [Top]
    Apr 28, 2005 - New Files and Folders in ASP.NET 2.0
    With the release of ASP.NET 2.0, Microsoft has greatly increased the power of ASP.NET by introducing a suite of new features and functionalities. As part of this release, ASP.NET 2.0 also comes with a host of new special files and folders that are meant to be used to implement a specific functionality. This article examines these new files and folders in detail and provides examples that demonstrate how to utilize them to create ASP.NET 2.0 applications.
    [Read This Article]  [Top]
    Mar 10, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 2, Cont'd
    Alex Homer continues his detailed look at the major changes to the DataSet class. In this part, he looks at two features that allow developers to work with data in a more structured and efficient way when using the DataSet with a SQL Server 2005 database server.
    [Read This Article]  [Top]
    Mar 9, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 2
    Alex Homer continues his detailed look at the major changes to the DataSet class. In this part, he looks at two features that allow developers to work with data in a more structured and efficient way when using the DataSet with a SQL Server 2005 database server.
    [Read This Article]  [Top]
    Mar 3, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 1, Cont'd
    In this article, Alex Homer looks at the changes between the version 1.x and version 2.0 DataSet and their associated classes, showing you how you can take advantage of the new features to improve your applications' capabilities and performance.
    [Read This Article]  [Top]
    Mar 2, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 1
    In this article, Alex Homer looks at the changes between the version 1.x and version 2.0 DataSet and their associated classes, showing you how you can take advantage of the new features to improve your applications' capabilities and performance.
    [Read This Article]  [Top]
    Feb 16, 2005 - Writing a Custom Membership Provider for the Login Control in ASP.NET 2.0
    In ASP.NET 2.0 and Visual Studio 2005, you can quickly program custom authentication pages with the provided Membership Login controls. In this article, Dina Fleet Berry examines the steps involved in using the Login control with a custom SQL Server membership database.
    [Read This Article]  [Top]
    Dec 29, 2004 - ClickOnce Deployment in .NET Framework 2.0
    In this article, Thiru Thangarathinam examines .NET 2.0's new ClickOnce deployment technology that is designed to ease deployment of Windows forms applications. This new technology not only provides an easy application installation mechanism, it also eases deployment of upgrades to existing applications.
    [Read This Article]  [Top]
    Dec 15, 2004 - A Sneak Peek at ASP.NET 2.0's Administrative Tools
    With ASP.NET 2.0, Microsoft has made great strides in increasing developer productivity and has made implementing previously complex solutions relatively easy. Where this version of ASP.NET really shines, however, is in its new administrative tools that allow developers to spend less time managing the configuration of the servers and software and more time developing great code.
    [Read This Article]  [Top]
    Nov 17, 2004 - The ASP.NET 2.0 TreeView Control
    Thiru Thangarathinam introduces ASP.NET 2.0's new TreeView control which provides a seamless way to consume and display information from hierarchical data sources. The article discusses this new control in depth and explains how to use this feature rich control in your ASP.NET applications.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

    Solutions
    Whitepapers and eBooks
    Microsoft Article: Will Hyper-V Make VMware This Decade's Netscape?
    Microsoft Article: 7.0, Microsoft's Lucky Version?
    Microsoft Article: Hyper-V--The Killer Feature in Windows Server 2008
    Avaya Article: How to Feed Data into the Avaya Event Processor
    Microsoft Article: Install What You Need with Windows Server 2008
    HP eBook: Putting the Green into IT
    Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
    Avaya Article: Setting Up a SIP A/S Development Environment
    IBM Article: How Cool Is Your Data Center?
    Microsoft Article: Managing Virtual Machines with Microsoft System Center
    HP eBook: Storage Networking , Part 1
    Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
    MORE WHITEPAPERS, EBOOKS, AND ARTICLES
    Webcasts
    Intel Video: Are Multi-core Processors Here to Stay?
    On-Demand Webcast: Five Virtualization Trends to Watch
    HP Video: Page Cost Calculator
    Intel Video: APIs for Parallel Programming
    HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
    Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
    MORE WEBCASTS, PODCASTS, AND VIDEOS
    Downloads and eKits
    Sun Download: Solaris 8 Migration Assistant
    Sybase Download: SQL Anywhere Developer Edition
    Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
    Red Gate Download: SQL Compare Pro 6
    Iron Speed Designer Application Generator
    MORE DOWNLOADS, EKITS, AND FREE TRIALS
    Tutorials and Demos
    How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
    eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
    IBM Article: Collaborating in the High-Performance Workplace
    HP Demo: StorageWorks EVA4400
    Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
    Microsoft How-to Article: Get Going with Silverlight and Windows Live
    MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES