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!

Persisting .NET Objects to SQL Server Using SQLXML and Serialization
By Gianluca Nuzzo
Rating: 3.7 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    After writing "Retrieving Objects from SQL Server Using SQLXML and Serialization" I'm exploring opportunities of saving back objects to database, using a schema definition file (that we designed in the previous article), and another technique that is included with SQLXML called UPDATEGRAMS.

    This article will describe this technique as designed from Microsoft; go through the creation of an UPDATEGRAM class that use serialization and custom class attributes to form appropriate xml streams can be sent to SQLSERVER to perform automatic generated statements.

    I will start from an overview of UPDATEGRAMS feature of Microsoft SQLXML that you can find in the help online when you install SQXML libraries on your machine, or on the MSDN site (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sqlxml3/htm/updategram_5kkh.asp) I will resume the concepts here saying that UPDATEGRAMS are xml documents that together with an xml schema definition are used by SQLXML libraries to automate commands creation and execution on SQLSERVER to update, insert and delete records.

    Each UPDATEGRAM is mainly formed by a sequence of SYNC elements; each of them is a set of operations that will be executed in the same transaction context. Each SYNC element can contain BEFORE and AFTER elements for each set of operations to be executed. BEFORE elements are used to locate or create records and AFTER elements hold changes to records. So if you provide an empty BEFORE element you are performing an insert. On the other hand, an empty AFTER is a delete operation. When both of them are present, SQLXML will generate something like "UPDATE AFTER where BEFORE", and this is the scenario that we'll focus on.

    Now, let's go back to the windows application of the previous article and add a new form to change some properties and update data back to SQLSERVER of any given Order.

    add double click handler and the code to open the form from the grid form:

    private void grd_orders_DoubleClick(object sender, EventArgs e)
       {
          Form f = new OrderForm(this.orders[this.grd_orders.CurrentRowIndex]);
          f.Visible=true;
       }
    

    in the load event bind the order to the controls...

    private void OrderForm_Load(object sender, System.EventArgs e)
       {
          this.lblOrderNum.Text = this.order.OrderID.ToString();
    
          //we don't want null dates, instead the control will be set to current or default
          if(this.order.OrderDate!=DateTime.MinValue)
             this.dtpOrderDate.Value = this.order.OrderDate;
          if(this.order.RequiredDate!=DateTime.MinValue)
             this.dtpRequiredDate.Value = this.order.RequiredDate;
    
          this.txtShipAddress.Text = this.order.ShipAddress;
          this.txtShipCity.Text = this.order.ShipCity;
          this.txtShipName.Text = this.order.ShipName;
          this.txtShipZip.Text=this.order.ShipPostalCode;
          this.txtShipCountry.Text = this.order.ShipCountry;
       }
    

    Now that you can see the Order ready to be edited let's start with the save button. We need to write a method (like getChanges()) to get values from controls in the Form and set them to the Order object. Our target is to generate an UPDATEGRAM, with the old order as the before node and the changed order as the after node, send it to SQLSERVER and the update should be automatic.

    First of all we need to define a method of having the before state (after state will be the current state of the object). I decided to use binary serialization to clone and compare object and this is my little helper class that will be used by base classes of entities in the project...

    public class CloneHelpers
       {
          public static object DeepClone(object source)
          {
             MemoryStream m = new MemoryStream();
             BinaryFormatter b = new BinaryFormatter();
             b.Serialize(m, source);
             m.Position = 0;
             return b.Deserialize(m);
                
          }
          public static bool DeepEquals(object objA,object objB)
          {
             MemoryStream serA = serializedStream(objA);
             MemoryStream serB = serializedStream(objB);
             if(serA.Length!=serA.Length)
                return false;
             while(serA.Position<serA.Length)
             {
                if(serA.ReadByte()!=serB.ReadByte())
                   return false;
             }
             return true;
    
          }
          public static MemoryStream serializedStream(object source)
          {
             MemoryStream m = new MemoryStream();
             BinaryFormatter b = new BinaryFormatter();
             b.Serialize(m, source);
             m.Position = 0;
             
             return m;
          }
       }
    

    Let's define the base business classes then:

    [Serializable]
       public abstract class BaseBusinessEntity 
       {
          public object DeepClone()
          {
             return CloneHelpers.DeepClone(this);
          }
    
       
          public bool DeepEquals(object obj)
          {
             return CloneHelpers.DeepEquals(this,obj);
          }
          
       }
    
    [Serializable]
       public abstract class BaseBusinessEntityCollection : CollectionBase
       {
          public object DeepClone()
          {
             return CloneHelpers.DeepClone(this);
          }
       }
    

    In the order form you can now have code and properties to define the initial state of the entity that you are working on:

    public OrderForm(OrdersMgmt.Order ord)
       {
          //get the order from the grid form
          this.order=ord;
          //set the initial state
          this.orderBefore = (OrdersMgmt.Order) ord.DeepClone();
    

    At this point you might say: let's serialize the object to xml in his initial state to make the Before node, then when properties of object are changed re-serialize the object to xml to obtain the After node, and that is...

    Let's have a look at a way of abstracting the UPDATEGRAM generation, and design a class to hold properties to correctly form and run the xml stream.

    We instantiate this class with the most important property: the XSD file.

    public updategram(string schemaFile)
       {
          //set the current schema to use when sending updategram to SQLSERVER
          this.schemaFilePath = schemaFile;
          //initialize the state of the updategram and open the xml document 
          this.InitUpdgDocument();
          this.syncCollection = new Hashtable();
       }
    

    The InitUpdgDocument() will start the xml document (I'm using the document object for simplicity I leave optimizations to your skills):

    private void InitUpdgDocument()
       {
          if(this.updgDocument==null)
          {
             //create empty updategram
             updgDocument = new XmlDocument();
             updgDocument.LoadXml("<ROOT xmlns:"+prefix+"=\""+ns+"\"></ROOT>");
    
          }
       }
    

    The syncCollection is holding all objects that must be modified with their initial state as key and in the actual state as value. Now that we have the UPDATEGRAM and the initial state for the form we can see what happen when we click the save button.

    private void btnUpdate_Click(object sender, System.EventArgs e)
       {
          //get form values and set entity values
          this.getChanges();
          //compare to object and create new sync node if something changed
          updg.Process(this.orderBefore,this.order);
          //commit all sync nodes created
          updg.Commit();
    
          //set new initial state
          this.orderBefore = (OrdersMgmt.Order) this.order.DeepClone();
    
          //this.Close();
       }
    

    In the getChages() operation I set order values from controls, then I call the process method of UPDATEGRAM to compare object and insert a new key/value entry in syncCollection if the two states are different. In this case we are working only on one object but changing multiple objects can happen without problems. Once all updates can be committed we call the Commit method of updategram that will do the actual update work on sql server let's have a look...

    public void Commit()
       {
          //cycle all syncs with original keys
          foreach(object objOriginal in this.syncCollection.Keys)
          {
             //get reference to changed object
             object objChanged = this.syncCollection[objOriginal];
    
             //initialize a the serializer provider
             UpdgXSerializer x = new UpdgXSerializer(objOriginal,objChanged);
             //get the serializer for the before element
             this.beforeSerializer = x.getUpdgSerializer(UpdategramElement.Before);
             //get the serializer for the after element
             this.afterSerializer = x.getUpdgSerializer(UpdategramElement.After);
    
             //create the sync element
             this.createSync();
    
             //create the before element
             this.BeginUpdate(objOriginal);
    
             //create the after element
             this.EndUpdate(objChanged);
          }
    
          //verify that we have a document to submit
          if(this.updgDocument==null)
             return;
    
    
          //create the stream with the xml document
          MemoryStream ms;
          ms = new MemoryStream();
          this.updgDocument.Save(ms);
          ms.Position = 0;
    
          try
          {
             //execute the xml stream
             XmlReader results = sqlxmlHelper.executeUpdateGram(this.schemaFilePath,ref ms);
          }
          catch(Exception ex)
          {
             throw new Exception("Error while committing operations to DB, "+ex.Message,ex);
          }
          finally
          {
             //clean up after submit
             ms.Close();
          }
    
          this.syncCollection = new Hashtable();
          updgDocument = null;
       }
    

    The default serialization will form xml containing all Order Lines one after the other as child nodes...

    <updg:before>
       <Order>
          <OrderID>10250</OrderID>
          ...
          <OrderLines>
             <OrderDetail>
                <Quantity>10</Quantity>
                <Discount>0</Discount>
                <Item>
                   <ProductID>41</ProductID>
                   <ProductName>Jack's New England Clam Chowder</ProductName>
                   <UnitPrice>9.65</UnitPrice>
                </Item>
                <OrderID>10250</OrderID>
                <ProductID>41</ProductID>
             </OrderDetail>
             <OrderDetail>
                <Quantity>35</Quantity>
                <Discount>0.15</Discount>
                <Item>
                   <ProductID>51</ProductID>
                   <ProductName>Manjimup Dried Apples</ProductName>
                   <UnitPrice>53</UnitPrice>
                </Item>
                <OrderID>10250</OrderID>
                <ProductID>51</ProductID>
             </OrderDetail>
    

    when sent to SQMXML will generate this error:

    so for each node (objects) we need to have an index or id to supply updg:id attribute. I took the quickest way by giving Order Detail object a read/write property with an attribute defining the way should be named and look in xml.

    [XmlAttribute(AttributeName="id",Namespace="urn:schemas-microsoft-com:xml-updategram")]
       public int OrderIDKey
       {
          get
          {
             return this.ProductID;
          }
          set
          {
          }
       }
    

    In this case the productID is a good id as it is unique for details inside an order, and the empty set is needed to make the property read/write, otherwise it would not be serialized in xml.

    I'll do the same for order object to enable multiple orders batch update:

    [XmlAttribute(AttributeName="id",Namespace="urn:schemas-microsoft-com:xml-updategram")]
       public int OrderIDKey
       {
          get
          {
             return OrderID;
          }
          set
          {
          }
       }
    

    Now we can inspect xml for the new UPDATEGRAM with attributes for order and order detail:

    <Order updg:id="10250">
      <OrderLines>
        <OrderDetail updg:id="41">
    

    in this case everything goes all right when sent to SQLSERVER.

    But as you should know nothing in IT is stable from the first time for ever so let's look at few other cases where the default serialization does not work and how to solve the problem.

    First null values handling. Everyone working with input fields in web forms has experienced the problem of a user cleaning a field and a blank not null value is stored in the database for string types or a default value for numbers or dates. Also a null property is serialized with an empty element, so SQLXML will not update that column.

    NULL handling in SQLXML is described in this article: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sqlxml3/htm/updategram_12p3.asp So you can use a default value defined at xml root element (in the example I use updg:nullvalue="|isnull|") then all elements containing that value will be updated with a DBNULL. I've chosen to use a public field to hold all property names that need to be nullified.

    [XmlArray("nullProps"),XmlArrayItem("prop")]
       public string[] nullProps;
    

    Expose a method for adding a property name to the list :

    public void nullProperty(string propertyName)
       {
          foreach(PropertyInfo pInfo in this.GetType().GetProperties()) 
          {
             if(pInfo.Name==propertyName)
             {
                if(nullProps!=null && Array.IndexOf((Array)nullProps,propertyName)==-1){
                   string[] tmp = (string[]) nullProps.Clone();
                   nullProps = new string[tmp.Length+1];
                   nullProps[0] = propertyName;
                   tmp.CopyTo(nullProps,1);
                }
                else
                   nullProps = new string[]{propertyName};
                break;
             }
          }
       }
    

    in the form getChanges() method will be easy to handle inserted null values like here below:

          if(this.txtShipZip.Text==string.Empty)
             this.order.nullProperty("ShipPostalCode");
          if(this.txtShipCountry.Text==string.Empty)
             this.order.nullProperty("ShipCountry");
    

    let's have a look at writeAfterXML operation of UPDATEGRAM class where we create the After Node and set null values:

    private void writeAfterXML(ref object obj,ref XmlElement after)
       {
          MemoryStream ms;
          StreamReader sr;
    
          ms = new MemoryStream();
    
          XSerializer.serialize(ref ms
             ,obj,this.afterSerializer);
    
          sr = new StreamReader(ms);
          sr.BaseStream.Position = 0;
    
          //remove declaration
          after.InnerXml = sr.ReadToEnd().Remove(0,23);
    
          //set null values
          //get the list of properies to set DBNULL for each object at any level
          XmlNodeList list = after.SelectNodes("//*[nullProps]");
          foreach(XmlNode node in list)
          {
             //select the list of properties
             XmlNodeList propsToNull = node.SelectNodes("nullProps/prop");
             foreach(XmlNode prop in propsToNull)
             {
                XmlNode property = node.SelectSingleNode(prop.InnerText);
                if(property!=null)
                   property.InnerText = UPDG_NULL_CODE;
             }
             //remove nullProps node to avoid sqlxml conflict
             node.RemoveChild(node.SelectSingleNode("nullProps"));
          }
    
          //remove empty elements
          list = after.SelectNodes("//*[.='']");
          foreach(XmlNode node in list)
          {
             node.ParentNode.RemoveChild(node);
          }
          sr.Close();
          ms.Close();
       }
    

    In the writeBeforeXML it's just a matter of removing properties to null nodes. I did a test on one order, deleting zip & country, saving and this is the result:

    Another issue is respecting relational data integrity and lookups value, let's say that we remove from the Order the first OrderLine, with this line of code

    this.order.OrderLines.RemoveAt(0);
    

    the subsequent xml serialization in the AFTER node will miss the deleted order line, and that's obvious, but it's not evident that this will cause deletion of not only Order Detail but related Products too, which in the case of Northwind database, where relationships are well defined will throw an exception (see figure below).

    Product is referenced by other order lines and no cascade action is performed when products are deleted. In another case where no relationship is present you need to find a way of not including this part of object in UPDATEGRAM. I did some meditation to decide a method of excluding these properties and I decided to go for customizing the way the object is serialized.

    So I created first an attribute that would sign properties to be excluded from xml serialization:

    public class LookupAttribute:System.Attribute
       {
          public LookupAttribute()   {}
       }
    

    then I thought about those properties that we need for sure all the time (like primary/foreign keys) and I created a second attribute :

    public class IntegrityCheckAttribute:System.Attribute
       {
          public IntegrityCheckAttribute()   {}
       }
    

    Now that I have properties defined like the Product in OrderDetail:

    [Lookup]
    public Product Item
    

    and all the primary/foreign keys defined like the OrderID in Order:

    [IntegrityCheck]
    public int OrderID
    

    I can create a custom Serializer for the objects that will exclude from xml serialization the marked properties depending at which state the objects are. Please read the MSDN article that describes XmlAttributeOverrides class: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemxmlserializationxmlattributeoverridesclasstopic.asp

    Here the constructor:

    public UpdgXSerializer(object objBefore,object objAfter)
       {
          //hold reference to before state
          this._Before=objBefore;
          //hold reference to after state
          this._After=objAfter;
       }
    

    then the main operation that return the Serializer object for the UDATEGRAM node:

    public XmlSerializer getUpdgSerializer(UpdategramElement updgElement)
       {
          //init. the collection of overrides
          XmlAttributeOverrides myOverrides = new XmlAttributeOverrides();
    
          Type objType=null;
          //choose the right object
          switch(updgElement)
          {
             case UpdategramElement.Before:
                //parse the object to retrive attribute overrides
                this.parseType(this._Before,ref myOverrides,updgElement);
                objType = this._Before.GetType();
    
                break;
             case UpdategramElement.After:
                this.parseType(this._After,ref myOverrides,updgElement);
                objType = this._After.GetType();
    
                break;
          }
          //advanced serializer with attribute overrides
          XmlSerializer retVal = new XmlSerializer(objType, myOverrides);
    
          return retVal;
       }
    

    the parseType private call start the actual job on finding those properties that we need to hide..

    private void parseType(object source,ref XmlAttributeOverrides xmloverrides,
    	UpdategramElement updgElement)
       {
          Type objType = source.GetType();
          // Iterate through all the properties of the class
          foreach(PropertyInfo pInfo in objType.GetProperties()) 
          {
             //get the attribute overrides for the property
             getAttributesForProperty(pInfo,ref xmloverrides,objType,updgElement);
             if(typeof(IList).IsAssignableFrom(pInfo.PropertyType))
             {
                //when we have non empty collection we cyle iterate the parsing operations
                IList val = (IList) pInfo.GetValue(source,null);
                if(val !=null && val.Count>0)
                {
                   parseType(val[0],ref xmloverrides,updgElement);
                }
             }
          }
       }
    

    getAttributesForProperty private call do the actual insert of attribute override...

    private void getAttributesForProperty(
          PropertyInfo pInfo,
          ref XmlAttributeOverrides xmloverrides,
          Type objType,
          UpdategramElement updgElement)
       {
          // need this as we start from the assumption that in the Before we need the
          // minimum in the After we need the more
          bool ignore = false;
    
          if(updgElement==UpdategramElement.Before)
          {
             ignore = true;
          }
    
          // Iterate through all the Attributes for each property.
          foreach (Attribute attr in Attribute.GetCustomAttributes(pInfo)) 
          {
             Type tmp = attr.GetType();
             //remove from before the lookup values and leave the primary/foreign keys
             if(updgElement==UpdategramElement.Before)
             {
                if(tmp==typeof(IntegrityCheckAttribute))
                {
                   ignore = false;
                }
                if(tmp==typeof(LookupAttribute))
                   ignore = true;
             }
                //remove from after node the lookup attribute (if it's not an insert)
             else if(updgElement==UpdategramElement.After)
             {
                if((tmp==typeof(LookupAttribute)) && this._Before!=null)
                   ignore=true;
             }
          }
          if(ignore)
          {
             XmlAttributes myAttributes = new XmlAttributes();
             myAttributes.XmlIgnore = true;
             xmloverrides.Add(objType,pInfo.Name,myAttributes);
          }
       }
    

    If you follow comments you should be able to understand the logic, and then see the final UPDATEGRAM for the Order object including the deletion of the first order line:

    <ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
       <updg:sync updg:nullvalue="|isnull|">
          <updg:before>
             <Order updg:id="10250">
                <OrderID>10250</OrderID>
                <OrderLines>
                   <OrderDetail updg:id="41">
                      <OrderID>10250</OrderID>
                      <ProductID>41</ProductID>
                   </OrderDetail>
                   <OrderDetail updg:id="51">
                      <OrderID>10250</OrderID>
                      <ProductID>51</ProductID>
                   </OrderDetail>
                   <OrderDetail updg:id="65">
                      <OrderID>10250</OrderID>
                      <ProductID>65</ProductID>
                   </OrderDetail>
                </OrderLines>
             </Order>
          </updg:before>
          <updg:after>
             <Order updg:id="10250">
                <OrderID>10250</OrderID>
                <OrderDate>1996-07-05T00:00:00.0000000+02:00</OrderDate>
                <RequiredDate>1996-08-07T00:00:00.0000000+02:00</RequiredDate>
                <ShippedDate>1996-07-12T00:00:00.0000000+02:00</ShippedDate>
                <Freight>65.83</Freight>
                <ShipName>Hanari Carnes</ShipName>
                <ShipAddress>Rua do Paulo, 69</ShipAddress>
                <ShipCity>Rio de Janeiro</ShipCity>
                <ShipPostalCode>283458</ShipPostalCode>
                <ShipRegion>RJ</ShipRegion>
                <ShipCountry>test</ShipCountry>
                <OrderLines>
                   <OrderDetail updg:id="51">
                      <Quantity>35</Quantity>
                      <Discount>0.15</Discount>
                      <OrderID>10250</OrderID>
                      <ProductID>51</ProductID>
                   </OrderDetail>
                   <OrderDetail updg:id="65">
                      <Quantity>15</Quantity>
                      <Discount>0.15</Discount>
                      <OrderID>10250</OrderID>
                      <ProductID>65</ProductID>
                   </OrderDetail>
                </OrderLines>
             </Order>
          </updg:after>
       </updg:sync>
    </ROOT>
    

    I think this prototype can be improved in many parts, like the last one that we faced, with a better comparison of the 2 object states and a better clean up of xml, or maybe you want to use the all the properties in both Before and After nodes to achieve something like dataset internal DiffGram way of preserving data integrity in disconnected environments, or maybe you can use timestamps for this.... it's really up to you and your implementation, the high level image here is that we have defined a draft framework that automate at entity level database read and write operations on SQLSERVER with SQLXML and the .Net Framework.

    Download Source Code

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Supporting Products/Tools
    Proposion N2N
    Proposion N2N connects Microsoft .NET applications to Lotus Notes and Lotus Domino databases. This ADO.NET managed data provider allows you to perform blindingly fast queries and updates of Notes data from ASP.NET pages, .NET web services, Windows, or Mobile applications. An innovative SQL-like query language leverages the unique features of Notes and makes collaborative software accessible to relational database programmers.
    [Top]
    Other Articles
    Sep 15, 2005 - Building an Image Keyword System
    Unlike text-based file formats image files aren't made up of words, which makes searching for an image file by keyword difficult. Instead of being able to simply open the file to see what it contains, we're stuck looking at the text around it and other metadata to determine the image's meaning. In this article, Ziran Sun shows you how to build a simple database-based image keyword system that allows you to associate keywords with images and use these keywords to make finding images easier.
    [Read This Article]  [Top]
    Apr 7, 2005 - A Step-by-Step Guide To Using MySQL with ASP.NET - Part 2
    In the second part of of his article on using MySQL with ASP.NET, Ziran Sun covers how to add a new MySQL user to the database server, assign the user the appropriate permissions, connect to the database, and build a simple ASP.NET page to perform a query.
    [Read This Article]  [Top]
    Feb 10, 2005 - A Step-by-Step Guide To Using MySQL with ASP.NET - Part 1
    Back in the days of classic ASP, if you were building a database-driven web site, your choice was either to invest a lot of money to get a copy of Microsoft SQL Server (or some other enterprise-ready database) or invest a lot of time finding a way to deal with the performance and scalability limitations of Microsoft Access. Luckily these days there's another viable alternative: MySQL.
    [Read This Article]  [Top]
    Jan 27, 2005 - Moving a Database from SQL Server 7.0 to SQL Server 2000
    Moving or copying a SQL Server database from one machine to another requires a lot of preparation in order to ensure a smooth transfer. In this article, Dina Fleet Berry examines the different methods and highlights the different issues associated with each of them.
    [Read This Article]  [Top]
    Jan 6, 2005 - Debugging a SQL Stored Procedure from inside SQL Server 2000 Query Analyzer
    There are many times when using SQL Server 2000 Query Analyzer to debug SQL statements is a better choice than debugging in Visual Studio .NET. In this article, Dina Fleet Berry explains why and walks you through the debugging process step-by step.
    [Read This Article]  [Top]
    Sep 14, 2004 - Transaction Processing in ADO.NET 2.0
    One area that stands out when comparing ADO.NET 1.x to ADO.NET 2.0 is transaction processing. Bill Ryan shows just how easy transaction processing has become with the TransactionScope object in ADO.NET 2.0.
    [Read This Article]  [Top]
    Sep 8, 2004 - Custom Object Data Binding with .NET
    Developers often use brute force coding to marshal data between the GUI and application objects. In this article, Luther Stanton explains how to use .NET's out-of-the box data-binding functionality to make this job much easier.
    [Read This Article]  [Top]
    Sep 2, 2004 - Queue MSMQ Messages from SQL Server
    Learn how to create a console application to queue a message in Microsoft Message Queuing (MSMQ) and then use an extended stored procedure to call the console application from a SQL Server trigger.
    [Read This Article]  [Top]
    Aug 30, 2004 - Tuning Up ADO.NET Connection Pooling in ASP.NET Applications
    Connection pooling increases the performance of Web applications by reusing active database connections instead of creating a new connection with every request. This article shows how to monitor the connection pool, diagnose a potential problem, and apply the appropriate fix.
    [Read This Article]  [Top]
    Jul 13, 2004 - Retrieving Objects from SQL Server Using SQLXML and Serialization
    This article will describe how to design a data access layer for a set of entities. You'll learn how to write an XSD schema and design two simple helper classes -- one for reading an XML stream from SQL Server using SQLXML and another for deserializing the XML stream.
    [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