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!

Using Visual Studio .NET Wizards to Create an N-Tiered Application - Part 3
By David Catherman
Rating: 4.5 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Table of Contents

    Using Visual Studio .NET Wizards to Create an N-Tiered Application

    Part 3 - Building the Business Tier

    In Part 1 and 2 of this series, we looked at using the Rapid Application Development (RAD) tools in Visual Studio to develop 3-tiered applications with a strong emphasis on Object Oriented Programming (OOP). By building Typed DataSet objects in a separate Business project and the Object Data Sources tool in our presentation layer, the parts of our application are isolated into tiers that can be compiled separately and even distributed to different servers if necessary.

    Domain Model Architecture

    While there are many different architecture models available today, there is one that fits the methodology promoted by Microsoft Visual Studio that is a balance between relational architecture and pure object-oriented architecture. This architecture has recently been promoted by several renowned architects such as Jimmy Nilsson and is known as the Domain Model Architecture. Instead of burying the Domain layer deep inside the Business tier, this model elevates it to a position that allows several different layers to have access to the data. Figure 1 shows how the model fits with Visual Studio 2005.


    Figure 1 - Domain Model Architecture with VS2005 implementation

    This model uses the Typed DataSet as the Domain layer. The TDS wraps the DataSet object with a set of classes, methods and properties to allow access to data in almost a pure object oriented manner and makes the most of using Intellisense. In Visual Studio 2005, theses classes are contained in the generated Designer sub-file of the DataSet in a Partial Class. Another Partial Class is provided in a sub-file that is customizable by the developer and is a good place to implement business logic that affects the data.

    In another part of the Designer sub-file, separated by namespace is the Data Access logic that provides all the ADO code needed to retrieve and update the data from a database. The classes generated are called Table Adapters and are Data Adapters wrapped in strongly typed properties and methods. While these classes are generated, you can extend them by adding code to a Partial Class for the Table Adapters.

    When first generated, the DataSet mirrors very closely the structure or schema of the database. Some architects complain that the DataSet is too tightly coupled with the database schema, but in reality only the Metadata is represented. All of the tables and fields can be renamed and mapped to better represent entities and columns if necessary. But if the database has been properly designed, this is not often necessary.

    Adding Business Layers

    Using the partial classes for business logic will work for minor code that deals directly with the data. Most enterprise developers prefer to have a separate class to contain the logic for each entity. I am currently working with the Mere Mortals Framework by Kevin McNeish which heavily uses business objects. It is fairly easy to use a Typed DataSet as we have in this example while also instantiating the separate business object classes and pointing them to a DataTable in the existing DataSet. In his way, you get the best of both worlds—the power and reusability of business object classes with all the business logic and the data sources wizards for ease of building screens.

    Business Logic

    As we saw in Part 2 of this series, one of the important parts of business logic is providing a pass-through for the application to call the Data Access layer. Each Table Adapter needs to be instantiated and a method provided to fill the DataTable in the DataSet. For those tables that are updateable, a method should also be provided to pass updates back to the database. For the Northwind DataSet containing 5 tables in the Part 2 example, here is the Data Access code needed:

    Imports ta = NorthwindDataSetTableAdapters
    Partial Public Class NorthwindDataSet
    
        Private taOrders As New ta.OrdersTableAdapter
        Private taOrderDetail As New ta.Order_DetailsTableAdapter
        Private taCustomer As New ta.CustomersTableAdapter
        Private taEmployee As New ta.EmployeesTableAdapter
        Private taProduct As New ta.ProductsTableAdapter
    
        Public Sub FillDataSetAll()
            Me.taOrders.Fill(Me.Orders)
            Me.taOrderDetail.Fill(Me.Order_Details)
            Me.taCustomer.Fill(Me.Customers)
            Me.taEmployee.Fill(Me.Employees)
            Me.taProduct.Fill(Me.Products)
        End Sub
    
        Public Sub UpdateOrders()
            Me.taOrders.Update(Me.Orders)
        End Sub
    
        Public Sub UpdateOrderDetails()
            Me.taOrderDetails.Update(Me.Order_Details)
        End Sub
    End Class
    

    This is a simplistic example where the DataTables are filled with all the records in the database. For larger databases, the fills can be done by passing a filter parameter.

    Parameterized Queries

    One of the options in the DataSet Designer that we have not covered yet is the ability to add multiple parameterized queries through which data can be retrieved from the database if you want something less than all the records in the table. If you open the dataset and right-click on one of the table adapter headers, you see a list of functions available. The Add Query option opens the Table Adapter Configuration Wizard with the options to use SQL statements, create new stored procedures, or use existing stored procedures. For simple queries you can use SQL statements but in a secure environment, it is best to use stored procedures to access the data. The ones generated by the Wizard are adequate, but you may use some that are generated by your DBA. If you do use existing SPs the next screen will allow you to select them for a list of all stored procedures in the database.


    Figure 2 - Table Adapter Command Type

    The next screen offers the choice of what the query will be used for. The options are: Select a set of rows, return a single value, Update, Delete, or Insert. Most often the query will be to return a set of rows, but the option to change the way an update or delete happens is interesting also.


    Figure 3 - Table Adapter Query Type

    Each query is defined by a SQL Statement which can be typed in here or built visually using the standard Visual Query Builder.


    Figure 4 - Table Adapter Select Statement

    At this point you can add a filter parameter to the query to only get orders for a specific customer


    Figure 5 - Visual Query Builder


    Figure 6 - Table Adapter Method Names

    The next screen in the Wizard allows you to edit the names for the FillBy (for existing DataTables) and GetDataBy (returns an DataTable object) types of methods. Clicking the Finish button will complete the query.

    The DataSet Designer will add another line to the Table Adapter section of the table representation showing the new method. Now the DataTable can be filled with only part of the orders by calling the FillByCustomerID and passing a CustomerID parameter.

    Using Optional Parameters

    Another way to provide flexibility in your table adapters is to use optional parameters and allow the user the choice of several different parameters with one call. In this example, we could make one query that would allow the user to fill by either the CustomerID or the EmployeeID by adding to the WHERE clause "OR @Parameter IS NULL" as follows.

    SELECT * 
    FROM Orders 
    WHERE (CustomerID = @CustomerID OR @CustomerID IS NULL) 
        AND (EmployeeID = @EmployeeID OR @EmployeeID IS NULL)
        AND NOT (@CustomerID IS NULL AND @EmployeeID IS NULL)
    

    In this example you can pass any or both parameters but if you don't pass any, you will get an empty result set.

    Typed DataSets handle optional parameters fairly well. The generator will create Nullable(Of Type) parameters for value types and correctly convert to dbnull.

    The only disadvantage with optional parameters in Typed DataSets is you have to take care of the parameters collection yourself. Most of the time you have to set the AllowDBNull property by hand, and the Wizard will reset its state every time you reconfigure the query.

    Filling a Table by Relation

    Since we have limited the number of records in the Orders table, we should also limit the rows when filling the Order Details table. It would be nice if Microsoft added a feature for filling by relationship, but it did not make it into this version. So we need to come up with a work around.

    If we were using stored procedures, we could use the Multiple Active Result Sets (MARS) feature of SQL Server 2005 to return the data for both tables at once. You have to add some extra code to map the result sets into the correct Data Tables, but it is not very difficult. Using the partial class for the Table Adapter is a good place to write this code since you have access to the Data Adapter object to add the TableMappings method.


    Figure 7 - Query to Fill Order Details by Relation

    Another approach would be to loop through the records in the Orders table and create a string of delimited OrderIDs to pass as a parameter to be used by an IN() clause filter. But the IN() clause does note accept a variable, so you would have to build the SQL Statement concatenating the list of IDs into the statement and using an EXEC function to execute it at runtime.

    The easiest solution is to add another query to the Order Details Table Adapter that joins the tables together and filters on the same CompanyID as shown in the Query Builder of Figure 7. If this is the primary query defining the Order Details table, this will not work since it is hard for the Update to know which table to update. But as a secondary query, it should work fine.

    Updating Multiple Tables

    In the previous article, I showed a very simple procedure for updating the dataset back to the database. But the update method requires special concern when updating related tables. If the tables are updated in the wrong order, you could end up trying to delete parent records before child record or inserting child record before inserting parent records.

    The correct sequence for updating related tables is to first send the deleted children, then update the parent table, and then update and add the children records. The GetChanges method of the DataTable allows for this functionality. First we create new temporary DataTables and define them as subsets of the current Data Table based on which records have been added or deleted. Then each of these temporary Data Tables is updated in the correct sequence. (Note: The format for this code can be found in the VB Code Snippets insert.)

        Public Sub UpdateDB()
            Dim DeletedChildRecords As DataTable = _
                Me.Order_Details.GetChanges(DataRowState.Deleted)
            Dim NewChildRecords As DataTable = _
                Me.Order_Details.GetChanges(DataRowState.Added)
            Dim ModifiedChildRecords As DataTable = _
                Me.Order_Details.GetChanges(DataRowState.Modified)
            Try
                If Not DeletedChildRecords Is Nothing Then
                    taOrderDetail.Update(DeletedChildRecords)
                    DeletedChildRecords.Dispose()
                End If
                taOrders.Update(Me.Orders)
                If Not ModifiedChildRecords Is Nothing Then
                    taOrderDetail.Update(ModifiedChildRecords)
                    ModifiedChildRecords.Dispose()
                End If
                If Not NewChildRecords Is Nothing Then
                    taOrderDetail.Update(NewChildRecords)
                    NewChildRecords.Dispose()
                End If
                Me.AcceptChanges()
            Catch ex As Exception
                Throw ex
            End Try
        End Sub
    

    Adding Other Business Logic

    The partial class of the DataSet is a great place to implement any business logic that has to do with actual data items. We used the partial class for the dataset to instantiate the table adapters, but there are also sub partial classes for each of the tables (row collections), individual rows of a table, and even the row change event. Outside of the dataset partial class, you can also access the partial class for each of the Table Adapters.

    For example, if you wanted to create method that would consolidate two orders for the same customer by moving all the Order Detail records from one Order to another, you could create the following class inside the DataSet partial class (sub-class):

    Partial Public Class OrdersDataSet
    ...
        Partial Public Class Order_DetailsDataTable
            Public Sub MoveDetailRecords(ByVal FromOrderID As Integer,
                ByVal ToOrderID As Integer)
    
                For Each row As Order_DetailsRow In Me.Select("OrderID=" & FromOrderID)
                    row.OrderID = ToOrderID
                Next
            End Sub
        End Class
    ...
    End Class
    

    Back in the form code the new method is accessible on the Intellisense list.


    Figure 8 - Customized Method in Intellisense

    Another example might be the need for a method that will copy the address information from the customer to the shipping section of the order.

       Partial Public Class OrdersRow
            Public Sub ShipToCustomer()
                If Me.CustomerID Is Nothing Then
                    MsgBox("Customer not defined") 'TODO: should throw an exception
                    Return
                End If
                Dim CustTable As CustomersDataTable = Me.Table.DataSet.Tables("Customers")
                Dim CustRow As CustomersRow = CustTable.FindByCustomerID(Me.CustomerID)
                Me.ShipName = CustRow.ContactName
                Me.ShipAddress = CustRow.Address
                Me.ShipCity = CustRow.City
                Me.ShipRegion = CustRow.Region
                Me.ShipPostalCode = CustRow.PostalCode
                Me.ShipCountry = CustRow.Country
            End Sub
        End Class
    

    Back in the form code, when you get a reference to an OrderRow object, the method is available to copy the shipping address.

    These are just a couple examples of how to build business logic in the partial class of the DataSet. The advantage is that all of the DataSet objects are available in context. If you were to create another specific class as your business object, you would always have to pass a reference to the dataset to access the data objects. In the above examples, the data object can be referenced as "Me" since the coding is inside the dataset object.

    Using Macros to Generate Data Access Code

    Since the code for the Data Access layer is very repetitive, varying only by the table name, this is a good place for code generation. There are many different code generators available, each with their strengths and short comings. Recently I have been investigating using macros to generate code. The advantage to this method is that the generation is done in the context of the IDE. All of the formatting, indentation, and End tags are inserted just like when you are typing the code manually.

    To create a macro, from the VS top line menu select Tools / Macros / Macros IDE. This will open another IDE similar to VS for editing macros. In the class list, right click on MyMacros and add a new class (or Module) called GenDataAccessLayer. Inside of the new class create the following method.

    The following macro uses reflection to look into the dataset, instantiate each table adapter and call the fill method of each. The following namespaces need to be included:

    Imports EnvDTE
    Imports EnvDTE80
    Imports System.Diagnostics
    Imports System.Reflection
    Imports System
    

    In a macro, the Visual Studio integrated development environment (DTE) contains a pointer to the active document which points to the item from the Solution Explorer that is open. The item also knows which project it is in.

    Public Sub DefineTAviaReflectionVB()
        Dim pItem As ProjectItem = DTE.ActiveDocument.ProjectItem
        Dim ItemName As String = pItem.Name.Substring(0, pItem.Name.LastIndexOf("."))
        Dim proj As Project = pItem.ContainingProject
        Dim line As String = ""
        Dim TableName As String
        Dim taList As String
        Dim UpdateList As String = ""
        Dim UpdateType As MethodInfo
    

    From the full project name, we can build the location of the actual assembly. If you are looking for a Windows Forms assembly rather than the Business class library, you should use the .EXE instead of the .DLL extension.

        ProjName = ProjName.Substring(0, ProjName.LastIndexOf("\") + 1)
        ProjName = ProjName & "bin\debug\" & proj.Name & ".dll"
    

    Once you have the assembly, you can load the assembly from the file. There should be a better way to get a reference to the assembly from the project itself, but I have not yet found one.

        Dim targetAssembly As Assembly = Assembly.LoadFrom(ProjName)
    

    Now loop through each Type in the assembly, looking for those in the group of dataset table adapters ending in "TableAdapter".

        For Each typ As Type In targetAssembly.GetTypes()
            If typ.FullName Like "*" & ItemName & "TableAdapters." & _
                     "*TableAdapter" Then
                TableName = typ.Name.Substring(0, _
               typ.Name.LastIndexOf("TableAdapter"))
    

    Here is where the line of code actually gets built.

                line = "Dim ta" & TableName & " As " & ItemName & _
               "TableAdapters." & typ.Name
                DTE.ActiveDocument.Selection.NewLine()
                DTE.ActiveDocument.Selection.Text = line
    

    Save the object name for building the fill methods later.

                taList &= "ta" & TableName & ","
    

    Check if the table adapter has an update method (actually it is easier to check for the Delete method) and store the table adapter for later use.

                UpdateType = typ.GetMethod("Delete")
                If UpdateType IsNot Nothing Then
                    UpdateList &= "ta" & TableName & ","
                End If
        Next
    

    Now build a method to call the fill method for each table adapter.

        DTE.ActiveDocument.Selection.EndOfLine()
        DTE.ActiveDocument.Selection.NewLine()    
        'Add the Update methods
        For Each ta As String In UpdateList.Split(",")
            If ta.Length > 0 Then
                DTE.ActiveDocument.Selection.Text = "Public Sub Update" + _ 
                    ta.Substring(2) + "()"
                DTE.ActiveDocument.Selection.NewLine()
                DTE.ActiveDocument.Selection.Text = ta & ".Update(" & _
                   ta.Substring(2) & ");"
                DTE.ActiveDocument.Selection.NewLine()
            End If
        Next    
        targetAssembly = Nothing
    End Sub
    

    This code applied to our Northwind example generates the following code:

    Partial Class NorthwindDataSet
        Dim taCustomers As New NorthwindDataSetTableAdapters.CustomersTableAdapter
        Dim taEmployees As New NorthwindDataSetTableAdapters.EmployeesTableAdapter
        Dim taOrder_Details As New NorthwindDataSetTableAdapters.Order_DetailsTableAdapter
        Dim taOrders As New NorthwindDataSetTableAdapters.OrdersTableAdapter
        Dim taProducts As New NorthwindDataSetTableAdapters.ProductsTableAdapter
    
        Public Sub FillAll()
            taCustomers.Fill(Customers)
            taEmployees.Fill(Employees)
            taOrder_Details.Fill(Order_Details)
            taOrders.Fill(Orders)
            taProducts.Fill(Products)
        End Sub
        Public Sub UpdateOrder_Details()
            taOrder_Details.Update(Order_Details)
        End Sub
        Public Sub UpdateOrders()
            taOrders.Update(Orders)
        End Sub
    End Class
    

    I would appreciate some feedback on the logic here. Is it better to leave the table adapter instantiated for the life of the dataset (is there a large memory hit for this object), or would it be better to instantiate it each time it is needed (what is the processor requirement to instantiate this object) and free up the memory. In this case, I chose to leave them instantiated so they would be available for the update call.

    Database Provider Independence

    One thing Microsoft did not get added to the Table Adapter logic is to take advantage of the Provider Pattern to allow switching between different back end database engines. The Provider Pattern is a combination of the Abstract Factory Pattern and a couple others to streamline the ability to switch between different back-ends without recompiling the application. This pattern is available in DotNetNuke, ASP.NET and a few other Microsoft technologies, but they did not have time to get it to work with the generated Table Adapters. Since I still have a need to develop an application that can be database independent, I have continued to pursue a strategy for accomplishing the feat.

    In my first attempt, I tried to change the connection string to a different source and then regenerate the dataset. This did not work because the dataset generator trying to use the old ADO connection type. But you can create another connection to the other database and inside the dataset generator, change which connection each table points to and then regenerate the table.

    To continue with our Northwinds example, the sample database from Microsoft is available in MS Access, FoxPro, and SQL Server. To demonstrate this procedure, I will convert our sample application so that it will run against the Access database as well as the SQL Server database. Where this is less complicated if the OLEDB provider were originally used for the SQL Server connection, this demonstration will use OLEDB provider for the Access database and continue to use the SQLClient provider for SQL Server.

    Our sample application currently is configured to work with the SQL Server connection. Before we change that to an Access Connection, let's save the current configuration so we can easily come back to it. Open the DataSet and open the Designer code file. (You may have to turn on the "Show All Files" option at the top of Solution Explorer in order to see the sub files under the DataSet.) There are two main sections inside the Designer file: the Partial Public Class OrdersDataSet and the Namespace OrdersDataSetTableAdapters. There are several rows of attributes decorating the class, but if you collapse the section by clicking the minus sign in the margin, you should see the two sections.


    Figure 9 - DataSet Designer code file

    If you highlight the Table Adapters section and press Ctrl+C, you are copying the whole section. Now create a new Class module in the project, name it OrdersDataSetTableAdapters.SQL and paste the copied code into it. Of course this will generate errors because of the duplication, but if we change the Namespace by adding a ".SQL" on the end of it, it should compile fine.

    The next step is to go back to the DataSet Designer for the Orders DataSet, right click on the Orders table and select Configure.... The Wizard starts on page 3, but you can click the Previous button twice to get back to the first page where the connection is defined. Select the connection for the Access database or click the New Connection button to create a new one. By adding a connection here, it will be recorded in Project settings and in the App.Config file.

    After changing the connection string, proceed through and finish the Configuration Wizard. The Table Adapter has now been changed to point to the Access database.


    Figure 10 - Changing Table Adapter Connections

    Continue this procedure for each table in the dataset and you will have converted the application to now use the Access database instead of SQL Server. You should be able to run the application and see the Access data. If you have doubts, you can try changing some of the information and then look into both the Access and SQL Server tables to see where it has changed.

    The next step is to capture the Table Adapters section from the Designer file and create another Class module Called OrderDataSetTableAdapters.Jet and paste in the code. Change the Namespace this time by adding a ".Jet" on the end of it.

    Now we can switch back and forth between Access and SQL Server simply by changing the extension of the Namespace on the Imports statement at the top of the Developers partial class file. Adding a ".Jet" points the table adapters to the code saved for connecting to Access.

    Imports ta = NorthwindDataSetTableAdapters.Jet
    Partial Public Class NorthwindDataSet
        Private taOrders As New ta.OrdersTableAdapter
        Private taOrderDetail As New ta.Order_DetailsTableAdapter
    ...
    

    While this is a large step in the right direction, it is not the final solution because you still have to build the project after changing the extension. In a true Provider Pattern, you should be able to make the change simply by changing a parameter in the App.Config file and never have to recompile. I plan to continue working on the problem and will probably come back with a solution in a future article. If any of you come up with an idea, please let me know.

    Conclusion

    I am still very impressed with Visual Studio 2005 and the advances made in developing data applications rapidly. I am finally using the actual release bits and all of this development done during the Beta cycle still works. One interesting change is the new attributes added to each class in the Designer code. One of the problems of working with Table Adapters is that they are not inherited from any base class nor do they implement any interface making it hard to apply object oriented techniques to them. The inclusion of the attributes should provide the links necessary to work with using CodeDom and reflection. Look for future articles as I figure out what is going on.

    About the Author

    David Catherman - CMI Solutions

    Email: DCatherman (at) CMiSolutions (dot) com

    David Catherman has 20+ years designing and developing database applications with specific concentration for the last 4-5 years on Microsoft .NET and SQL Server. He is currently Application Architect and Senior Developer at CMI Solutions using Visual Studio and SQL Server 2005. He has 3 MCP certifications in .NET and is pursuing MCSD.

    Using Visual Studio .NET Wizards to Create an N-Tiered Application

  • 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: HyperV-The Killer Feature in WinServer ‘08
    Avaya Article: How to Feed Data into the Avaya Event Processor
    Microsoft Article: Install What You Need with Win Server ‘08
    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