MSDN Magazine > Issues and Downloads > 2003 > May >  Web Q&A: Storing SQL Data, URL Query Length, an...
Web Q&A
Storing SQL Data, URL Query Length, and More
Edited by Nancy Michell


Q What's the best way to store large amounts of XML data in SQL Server™? What are the performance implications of storing it in large chunks versus breaking it out into tables?
Q What's the best way to store large amounts of XML data in SQL Server™? What are the performance implications of storing it in large chunks versus breaking it out into tables?

A Different criteria play a role in that decision. If the data in the XML document is highly structured and fits into a relational model, it is often queried on a granular level, and you rarely need to get the XML back into its original form (in other words, order does not matter). In this case, decomposition into columnar data is better. If you have more document-oriented XML where order matters and recomposition costs are high, a Character Large Object or XML datatype-like approach is better.
A Different criteria play a role in that decision. If the data in the XML document is highly structured and fits into a relational model, it is often queried on a granular level, and you rarely need to get the XML back into its original form (in other words, order does not matter). In this case, decomposition into columnar data is better. If you have more document-oriented XML where order matters and recomposition costs are high, a Character Large Object or XML datatype-like approach is better.

Q When I send an XML query to SQL Server in a URL, after its length goes over about 1000 characters, I get the following error. Is it a bug?
<H3>ERROR: 400.100 Bad Request</H3><b>HResult:</b>
0x80004005<br><b>Source:</b> Microsoft SQL isapi
extension<br><b>Description:</b> The URL exceeds maximum length.<br>
Q When I send an XML query to SQL Server in a URL, after its length goes over about 1000 characters, I get the following error. Is it a bug?
<H3>ERROR: 400.100 Bad Request</H3><b>HResult:</b>
0x80004005<br><b>Source:</b> Microsoft SQL isapi
extension<br><b>Description:</b> The URL exceeds maximum length.<br>

A This limitation is by design. It was introduced as part of the security push for SQLXML 3.0 SP1. The length of the query part of the URL is limited to 1024 characters. If you want to send more information to this virtual directory, you need to use HTTP POST.
A This limitation is by design. It was introduced as part of the security push for SQLXML 3.0 SP1. The length of the query part of the URL is limited to 1024 characters. If you want to send more information to this virtual directory, you need to use HTTP POST.
If you are using POST, then the SQLXML ISAPI limits the amount of data that can be posted to this maximum value. It's up to you to choose the right value for your scenarios. You can still post large query requests using POST, but not through the URL. POST size is not unlimited, but it's configurable. What's specified as the maximum size of POST queries still applies. You can set it in Microsoft® Internet Information Services (IIS), as shown in Figure 1. Using ServerXmlHTTP should allow you to post larger data.
Figure 1 Maximum POST Size 

Q Is there a maximum number of classes that can be used in a single Visual Basic® 6.0 project?
Q Is there a maximum number of classes that can be used in a single Visual Basic® 6.0 project?

A There is, but it's not a fixed number. As stated in Visual Basic 6.0 Programmer's Guide (Microsoft Press, 1998), the module entries table accepts up to 125 bytes per module, with a total limit of 64KB, resulting in about 400 modules per project. This includes classes, forms, and modules.
A There is, but it's not a fixed number. As stated in Visual Basic 6.0 Programmer's Guide (Microsoft Press, 1998), the module entries table accepts up to 125 bytes per module, with a total limit of 64KB, resulting in about 400 modules per project. This includes classes, forms, and modules.
If you exceed this, you'll get a strange error. Your only hope is to reduce the number of classes by splitting your project into parts, combining the functionality of multiple classes into one, or upgrading to Visual Basic .NET.

Q I have the following class:
Public Type MyType
    SimpleValue As Integer
End Type
Private pTypeValue As MyType
  
Public Property Get MyTypeValue() As MyType
    MyTypeValue = pTypeValue
End Property

Public Property Let MyTypeValue(ByRef Value As MyType)
    pTypeValue = Value
End Property
The code using this class looks like the following:
Dim MyObject As Class1
Set MyObject = New Class1

Dim x As MyType
x.SimpleValue = 1
MyObject.MyTypeValue = x
MsgBox MyObject.MyTypeValue.SimpleValue
I need to know if I can assign only a single value to "MyTypeValue", like this:
MyObject.MyTypeValue.SimpleValue = 7
Q I have the following class:
Public Type MyType
    SimpleValue As Integer
End Type
Private pTypeValue As MyType
  
Public Property Get MyTypeValue() As MyType
    MyTypeValue = pTypeValue
End Property

Public Property Let MyTypeValue(ByRef Value As MyType)
    pTypeValue = Value
End Property
The code using this class looks like the following:
Dim MyObject As Class1
Set MyObject = New Class1

Dim x As MyType
x.SimpleValue = 1
MyObject.MyTypeValue = x
MsgBox MyObject.MyTypeValue.SimpleValue
I need to know if I can assign only a single value to "MyTypeValue", like this:
MyObject.MyTypeValue.SimpleValue = 7

A Well, you can assign it, but it doesn't actually accomplish anything. MyObject.MyTypeValue returns a copy of the internal structure, and you're making a change to the copy, which will be thrown away as soon as the line of code completes execution.
A Well, you can assign it, but it doesn't actually accomplish anything. MyObject.MyTypeValue returns a copy of the internal structure, and you're making a change to the copy, which will be thrown away as soon as the line of code completes execution.
Enabling you to access a structure that is internal to a class instance is inherently unsafe because the class can be destroyed, along with the memory for the structure. If you want to do this, though, you have two options. You can make MyType into a class or you can get a copy of the structure, edit it, and assign it back into the class as an atomic unit when you're finished with it.
Note that the copy in/copy out is not very expensive unless you're moving strings and arrays, in which case you can end up making deep copies of large amounts of data.

Q Is there a way for an ActiveX® control to detect if it is embedded in a Visual Basic 6.0 form? I need a public interface that the control can query using QueryInterface on the client site that hosts it.
Q Is there a way for an ActiveX® control to detect if it is embedded in a Visual Basic 6.0 form? I need a public interface that the control can query using QueryInterface on the client site that hosts it.

A For a control created in Visual Basic, the following will work:
TypeOf UserControl.Extender Is VBControlExtender
For a control not built in Visual Basic, you can get the extender object by following these steps:
  1. Call IOleObject::GetClientSite
  2. Query the client site for IOleControlSite using QueryInterface
  3. Query the GetExtendedControl method on the control site using QueryInterface
  4. Query the extended control for VBControlExtender (IID={164CBDD0-7321-11D1-A1E8-00A0C90F2731}) using QueryInterface
A For a control created in Visual Basic, the following will work:
TypeOf UserControl.Extender Is VBControlExtender
For a control not built in Visual Basic, you can get the extender object by following these steps:
  1. Call IOleObject::GetClientSite
  2. Query the client site for IOleControlSite using QueryInterface
  3. Query the GetExtendedControl method on the control site using QueryInterface
  4. Query the extended control for VBControlExtender (IID={164CBDD0-7321-11D1-A1E8-00A0C90F2731}) using QueryInterface

Q How can I tell what language an operating system is running in?
Q How can I tell what language an operating system is running in?

A GetSystemDefaultLCID is very helpful for systems running Windows® 9x (where the setting cannot be changed), but does not do much for Windows NT®, where it can be changed. To achieve this on Windows NT you will need to check the language version of specific files such as kernel32.dll. On Windows 2000 or Windows XP, you can use the GetUserDefaultUILanguage API. You can get more info on this at http://www.microsoft.com/globaldev.
A GetSystemDefaultLCID is very helpful for systems running Windows® 9x (where the setting cannot be changed), but does not do much for Windows NT®, where it can be changed. To achieve this on Windows NT you will need to check the language version of specific files such as kernel32.dll. On Windows 2000 or Windows XP, you can use the GetUserDefaultUILanguage API. You can get more info on this at http://www.microsoft.com/globaldev.

Q Is JScript® on a DHTML page executed in a single thread? What about cross-frame function invocation? If not, what should I do if I need to have a critical section in a JScript function?
Q Is JScript® on a DHTML page executed in a single thread? What about cross-frame function invocation? If not, what should I do if I need to have a critical section in a JScript function?

A All script code for a window is executed from a single thread. You don't have to worry about cross-frame calls in a single window. You do have to be careful if you are making calls between windows. The JScript code is executed in a single-threaded apartment thread and therefore you'll never need a critical section in the classical sense. However, you do need to be concerned because whenever a callout is made from one window, a call-in can occur from a secondary window. Callouts can happen pretty much on any line of JScript code because they will occur if the garbage collector runs and releases a proxy to an object on a different thread.
A All script code for a window is executed from a single thread. You don't have to worry about cross-frame calls in a single window. You do have to be careful if you are making calls between windows. The JScript code is executed in a single-threaded apartment thread and therefore you'll never need a critical section in the classical sense. However, you do need to be concerned because whenever a callout is made from one window, a call-in can occur from a secondary window. Callouts can happen pretty much on any line of JScript code because they will occur if the garbage collector runs and releases a proxy to an object on a different thread.

Q I want to open Microsoft Internet Explorer with a specific Web site already loaded. What is the best way to do this?
Q I want to open Microsoft Internet Explorer with a specific Web site already loaded. What is the best way to do this?

A Try this:
Set oShell = CreateObject("Wscript.Shell")
oShell.Exec ("C:\Program Files\Internet Explorer\IEXPLORE.EXE
http://www.msn.com")
A Try this:
Set oShell = CreateObject("Wscript.Shell")
oShell.Exec ("C:\Program Files\Internet Explorer\IEXPLORE.EXE
http://www.msn.com")
Or better yet, add a little error handling, and find the local hard drive location. Not everyone installs their operating system to the C drive, so hard coding C is generally not a good idea (see Figure 2).
Set oShell = CreateObject("Wscript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")

ProgramFiles = oShell.ExpandEnvironmentStrings("%ProgramFiles%")

IEPath = ProgramFiles & "\Internet Explorer\IEXPLORE.EXE"

if FSO.FileExists(IEPath) then
 
            oShell.Exec (IEPath & " http://www.msn.com")
else
            Wscript.Echo "Unable to find Internet Explorer executable."
            Wscript.quit 2989
end if
You could avoid calling iexplore.exe in a shell altogether:
Set IeWindow = wscript.CreateObject("InternetExplorer.Application")
IeWindow.Navigate "http://www.msn.com"   
IeWindow.Visible = 1
Finally, you could use the following statement:
Set oShell = CreateObject("Wscript.Shell")
oShell.run ("http://www.msn.com")

Q I recently inherited a project which contains JScript and I really need to learn how to debug it. The project is written in C++ and JScript, in both .htm and .js format.
Q I recently inherited a project which contains JScript and I really need to learn how to debug it. The project is written in C++ and JScript, in both .htm and .js format.
I installed Visual Studio® .NET because it has a script debugger. I opened up the .exe and one of the .htm files that I'd like to debug. I set a breakpoint on a line that I know gets hit when I run the program, but when I start the program the breakpoint symbol has a "?" in it and the tooltip says that in "TryWebService.htm, line 10667 character 31 the breakpoint will not currently be hit. No executable code is currently loaded at this location."
However, I know that part of the JScript is indeed getting executed. How can I set a valid breakpoint?

A In the properties of the project you're debugging there will be a number of checkboxes for managed code, unmanaged code, and script code—you need to check which kind you are intending to debug. Here's a few links that may help you with the script debugging: Debug Client-Side Script in Visual Basic .NET, and BUG: Debugger Skips Client-Side Breakpoints in ASP.NET Projects. Most of the information in these links is about ASP.NET projects, but the sections on client-side debugging should be helpful.
A In the properties of the project you're debugging there will be a number of checkboxes for managed code, unmanaged code, and script code—you need to check which kind you are intending to debug. Here's a few links that may help you with the script debugging: Debug Client-Side Script in Visual Basic .NET, and BUG: Debugger Skips Client-Side Breakpoints in ASP.NET Projects. Most of the information in these links is about ASP.NET projects, but the sections on client-side debugging should be helpful.

Q I need to know how to free the memory allocated by the array in JScript created here:
<%@language="JSCRIPT"%>
<%
var m_aTmp = new Array();
for(var idxArr=0;idxArr<=1000;idxArr++)
m_aTmp[idxArr] = "TESTING\n" ;
%>
<%=m_aTmp%>
Q I need to know how to free the memory allocated by the array in JScript created here:
<%@language="JSCRIPT"%>
<%
var m_aTmp = new Array();
for(var idxArr=0;idxArr<=1000;idxArr++)
m_aTmp[idxArr] = "TESTING\n" ;
%>
<%=m_aTmp%>

A JScript has garbage collection, but you can also assign a null value or an empty string and the object will get cleaned up:
for (i = 0; i <= 1000;i++)
{
    m_aTmp[i] = "";
}//end for
A JScript has garbage collection, but you can also assign a null value or an empty string and the object will get cleaned up:
for (i = 0; i <= 1000;i++)
{
    m_aTmp[i] = "";
}//end for
Also, after the new allocation you can force the garbage collection to run immediately with the undocumented CollectGarbage function, which was implemented mainly for debugging purposes and can be a great help when debugging script/COM objects.
Don't use any undocumented API ( | Method | Function | ...) outside of debugging or in release products. Also note that calling CollectGarbage does not guarantee that all memory that can be freed is released. A garbage collection may trigger destructors, which then cause more memory to become collectable.
JScript is an automatic storage language. If you care about exactly when objects are released, you should be using a language such as C, which allows you to precisely control object lifetime.

Got a question? Send questions and comments to webqa@microsoft.com.


Thanks to Paul Andrew, Earl Beaman, Sébastien Bovo, Marc Cauchy, Jeffrey Cline, Matt Curland, Edson Dos Santos, Jin Feng, Eunyoung Go, Madhuvan Gupta, Doug Hettinger, Harish Jayakumar, Julia Jia, Eric Lippert, Srinivas Somu, Maoni Stephens, Matteo Teruzzi, Michael Woodland, Rok Yu


Page view tracker