SQL Server Central
BLOG: Fair Discussion of Connection Pooling and Timeouts
Eric White’s Blog
MSDN: T-SQL UNION
Building Better Business Applications Using the 2007 Microsoft Office System
MSDN Screencasts - Click a Popular tag
Windows Workflow Foundation - ScottGu's Blog
B# .NET Blog
Entity Framework Video
C# Open Source Code projects to jump start development.
VB.NET <-> C# Excerpt Conversion Tool
Code Samples in VB.NET and C# using the System.IO.StreamReader object with the -Using- statement.
VB.NET
Imports System.IO
Using reader As StreamReader = New StreamReader(filenamepath)
While Not reader.EndOfStream()
Console.WriteLine(reader.ReadLine())
End While
End Using
C#
using System.IO
using (StreamReader reader = new StreamReader(filenamepath))
{
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine();
}
}
Listing 1 contains two class definitions written in
VB.NET, with the second class definition starting with the partial
keyword. Both class definitions may reside in two different physical
files. Functionally, Listing 1 is equivalent to Listing 2.
So, what are the uses for partial classes? Here are some good reasons to use partial classes:
- They
allow programmers on your team to work on different parts of a class
without needing to share the same physical file. While this is useful
for projects that involve big class files, be wary: If you find your
class file getting too large, it may well signal a design fault and
refactoring may be required. - The most compelling reason
for using partial class is to separate your application business logic
from the designer-generated code. For example, the code generated by
Visual Studio 2005 for a Windows Form is kept separate from your
business logic (we will discuss this in a later section). This will
prevent developers from messing with the code that is used for the UI.
At the same time, it will prevent you from losing your changes to the
designer-generated code when you change the UI.
The syntax of partial classes in VB.NET and C# differs
slightly. The following shows the implementation of partial classes in
C#:
'***************************** VB.NET *********************************** Listing 1 '---File1.vb--- Public Class Class1 Public Sub method1() End Sub End Class '---File2.vb--- Partial Public Class Class1 Public Sub method2() End Sub End Class Listing 2 '---File1.vb--- Public Class Class1 Public Sub method1() End Sub Public Sub method2() End Sub End Class // ***************************** C# *********************************** // In C#, the "partial" keyword must appear in all class definitions public partial class MyClass1 { public MyClass1() { //implementation here } } public partial class MyClass1 { //implementation here }
VB.NET provides nullable value types. When a nullable database field is returned for a value type, it will be stored in a .Net Nullable Type.
Example: CREATE TABLE Test ( CreateDate DATETIME NULL ) In VB.NET, these fields are declared as Dim createDate Date? Bad: ' This will throw an exception if createDate is Null If (createDate > Now) Good: If (column1.HasValue AndAlso Column1 > 5) ... If (createDate.HasValue AndAlso createDate > Now) ...
This is really the difference between Null and Nothing. One is for
Object types (like the String type) and one is for Scalar types (like int). This
needs a bit more research. See http://msdn2.microsoft.com/en-us/library/1t3y8s4s.aspx.
class NullableExample
{
static void Main()
{
int? num = null;
if (num.HasValue == true)
{
System.Console.WriteLine("num = " + num.Value);
}
else
{
System.Console.WriteLine("num = Null");
}
// y is set to zero
int y = num.GetValueOrDefault();
// num.Value throws an InvalidOperationException if num.HasValue is false
try
{
y = num.Value;
}
catch (System.InvalidOperationException e)
{
System.Console.WriteLine(e.Message);
}
}
}
The example will display the output:
num = Null
Nullable object must have a value.
TreeView Node Example.
Sub PopulateNode(ByVal source As Object, ByVal e As TreeNodeEventArgs) Dim node As TreeNode = e.Node If (node.Value = "Demos") Then node.Value = "~/" End If Dim dirs() As String = Directory.GetDirectories("C:\Documents and Settings\Gary\Favorites") ' Enumerate directories Dim dir As String For Each dir In dirs Dim virtualDir As String = node.Value.TrimEnd(_slashArray) & "/" & Path.GetFileName(dir) Dim newNode As TreeNode = New TreeNode(Path.GetFileName(dir), virtualDir) If (Directory.GetFiles(dir).Length > 0 Or Directory.GetDirectories(dir).Length > 0) Then newNode.PopulateOnDemand = True End If node.ChildNodes.Add(newNode) Next ' Enumerate files Dim files() As String = Directory.GetFiles("C:\Documents and Settings\Gary\Favorites") Dim file As String For Each file In files Dim newNode As TreeNode = New TreeNode(Path.GetFileName(file), Path.GetFileName(file), String.Empty, "http://www.msn.com", "blank") node.ChildNodes.Add(newNode) Next End Sub
Some description.
Public Class Class1 Private _FirstDate As DateTime = DateTime.MinValue Private _LaterDate As DateTime = DateTime.MinValue Private _Over60Days Public Property FirstDate() As DateTime Get Return _FirstDate End Get Set(ByVal value As DateTime) _FirstDate = value End Set End Property Public Property LaterDate() As DateTime Get Return _LaterDate End Get Set(ByVal value As DateTime) _LaterDate = value End Set End Property Public ReadOnly Property Over60Days() As Boolean Get If Not (_FirstDate = DateTime.MinValue Or _LaterDate = DateTime.MinValue) Then Return ((_FirstDate.Date - _LaterDate.Date()).Days > 60) Else Return False End If End Get End Property End Class Module Module1 Sub Main() Dim a As Boolean If False Or (True And False) Or (False And False) Then a = True Else a = False End If Dim c1 As Char? = Nothing Dim b As Boolean Dim myObj As New Class1 Console.WriteLine(myObj.Over60Days) myObj.LaterDate = DateTime.Now Console.WriteLine(myObj.Over60Days) myObj.FirstDate = (DateTime.Now.AddDays(30)) Console.WriteLine(myObj.Over60Days) myObj.FirstDate = (DateTime.Now.AddDays(61)) Console.WriteLine(myObj.Over60Days) End Sub End Module
System.DateTime.MinValue.Date // 1/1/0001 12:00:00 AM System.DateTime.MinValue.Day // 1 System.DateTime.MinValue.DayOfWeek // Monday System.DateTime.MinValue.DayOfYear // 1 System.DateTime.MinValue.Hour // 0 System.DateTime.MinValue.IsDaylightSavingTime() // False System.DateTime.MinValue.Kind // Unspecified System.DateTime.MinValue.Millisecond // 0 System.DateTime.MinValue.Minute // 0 System.DateTime.MinValue.Month // 1 System.DateTime.MinValue.Second // 0 System.DateTime.MinValue.Ticks() // 0 System.DateTime.MinValue.TimeOfDay // 00:00:00 System.DateTime.MinValue.ToBinary() // 0 System.DateTime.MinValue.ToFileTime() // Not a valid Win32 FileTime. System.DateTime.MinValue.ToFileTimeUtc() // Not a valid Win32 FileTime. System.DateTime.MinValue.ToLocalTime() // 1/1/0001 12:00:00 AM System.DateTime.MinValue.ToLongDateString() // Monday, January 01, 0001 System.DateTime.MinValue.ToLongTimeString() // 12:00:00 AM System.DateTime.MinValue.ToOADate() // 0 System.DateTime.MinValue.ToShortDateString() // 1/1/0001 System.DateTime.MinValue.ToShortTimeString() // 12:00 AM System.DateTime.MinValue.ToString() // 1/1/0001 12:00:00 AM System.DateTime.MinValue.ToUniversalTime() // 1/1/0001 6:00:00 AM System.DateTime.MinValue.Year // 1
System.DateTime.MaxValue.Date // 12/31/9999 12:00:00 AM System.DateTime.MaxValue.Day // 31 System.DateTime.MaxValue.DayOfWeek // Friday System.DateTime.MaxValue.DayOfYear // 365 System.DateTime.MaxValue.Hour // 23 System.DateTime.MaxValue.IsDaylightSavingTime() // False System.DateTime.MaxValue.Kind // Unspecified System.DateTime.MaxValue.Millisecond // 999 System.DateTime.MaxValue.Minute // 59 System.DateTime.MaxValue.Month // 12 System.DateTime.MaxValue.Second // 59 System.DateTime.MaxValue.Ticks() // 3155378975999999999 System.DateTime.MaxValue.TimeOfDay // 23:59:59.9999999 System.DateTime.MaxValue.ToBinary() // 3155378975999999999 System.DateTime.MaxValue.ToFileTime() // 2650467743999999999 System.DateTime.MaxValue.ToFileTimeUtc() // 2650467743999999999 System.DateTime.MaxValue.ToLocalTime() // 12/31/9999 5:59:59 PM System.DateTime.MaxValue.ToLongDateString() // Friday, December 31, 9999 System.DateTime.MaxValue.ToLongTimeString() // 11:59:59 PM System.DateTime.MaxValue.ToOADate() // 2958465.99999999 System.DateTime.MaxValue.ToShortDateString() // 12/31/9999 System.DateTime.MaxValue.ToShortTimeString() // 11:59 PM System.DateTime.MaxValue.ToString() // 12/31/9999 11:59:59 PM System.DateTime.MaxValue.ToUniversalTime() // 12/31/9999 11:59:59 PM System.DateTime.MaxValue.Year // 9999
The syntax of a format item is as follows:
{index[,length][:formatString]}
index | The zero-based position in the parameter list of the object to be formatted. If the object specified by index is null reference (Nothing in Visual Basic), the format item is replaced by String..::.Empty . Because this overload has only a single object in its parameter list, the value of index must always be 0. If there is no parameter in the index position, a FormatException is thrown. |
,length | The minimum number of characters in the string representation of the parameter. If positive, the parameter is right-aligned; if negative, it is left-aligned. |
:formatString | A standard or custom format string that is supported by the parameter. |
//Standard Numeric Format Specifiers --------------------------------------------------------------------------------- {0:C}, -123 Currency: . . . . . . . . ($123.00) {0:D}, -123 Decimal:. . . . . . . . . -123 {1:E},-123.45f Scientific: . . . . . . . -1.234500E+002 {1:F},-123.45f Fixed point:. . . . . . . -123.45 {0:G}, -123 General:. . . . . . . . . -123 (default):. . . . . . . . -123 (default = 'G') {0:N}, -123 Number: . . . . . . . . . -123.00 {1:P},-123.45f Percent:. . . . . . . . . -12,345.00 % {1:R},-123.45f Round-trip: . . . . . . . -123.45 {0:X}, -123 Hexadecimal:. . . . . . . FFFFFF85
Standard Numeric Format Specifiers --------------------------------------------------------------------------------- enum Color {Yellow = 1, Blue, Green}; {0:G},Color.Green General:. . . . . . . . . Green (default):. . . . . . . . Green (default = 'G') {0:F},Color.Green Flags:. . . . . . . . . . Green (flags or integer) {0:D},Color.Green Decimal number: . . . . . 3 {0:X},Color.Green Hexadecimal:. . . . . . . 00000003
Standard DateTime Format Specifiers --------------------------------------------------------------------------------- String.Format("{0:d}", DateTime.Now)); Short date: . . . . . . . 8/18/2009 String.Format("{0:D}", DateTime.Now)); Long date:. . . . . . . . Tuesday, August 18, 2009 String.Format("{0:t}", DateTime.Now)); Short time: . . . . . . . 10:52 PM String.Format("{0:T}", DateTime.Now)); Long time:. . . . . . . . 10:52:22 PM String.Format("{0:f}", DateTime.Now)); Full date/short time: . . Tuesday, August 18, 2009 10:52 PM String.Format("{0:F}", DateTime.Now)); Full date/long time:. . . Tuesday, August 18, 2009 10:52:22 PM String.Format("{0:g}", DateTime.Now)); General date/short time:. 8/18/2009 10:52 PM String.Format("{0:G}", DateTime.Now)); General date/long time: . 8/18/2009 10:52:22 PM String.Format("{0:M}", DateTime.Now)); Month:. . . . . . . . . . August 18 String.Format("{0:R}", DateTime.Now)); RFC1123:. . . . . . . . . Tue, 18 Aug 2009 22:52:22 GMT String.Format("{0:s}", DateTime.Now)); Sortable: . . . . . . . . 2009-08-18T22:52:22 String.Format("{0:u}", DateTime.Now)); Universal sortable: . . . 2009-08-18 22:52:22Z (invariant) String.Format("{0:U}", DateTime.Now)); Universal full date/time: Wednesday, August 19, 2009 3:52:22 AM String.Format("{0:Y}", DateTime.Now)); Year: . . . . . . . . . . August, 2009 String.Format("{0:MM/dd/yyyy}", DateTime.Now)); Formatted DateTime: . . . 08/18/2009 String.Format("{0:yyyy-MM-dd}", DateTime.Now)); Formatted DateTime: . . . 2009-08-18
DateTime dt = DateTime.Now; dt.ToString("d") // 8/18/2009 Short Date dt.ToString("%d") // 18 Day number dt.ToString("M?d") // 8?18 Month and day number dt.ToString("dd") // 18 Day number, two digits dt.ToString("ddd") // Tue Abbreviated day name dt.ToString("dddd") // Tuesday Full day name dt.ToString("f") // Tuesday, August 18, 2009 10:34 PM Full (long date, short time) dt.ToString("%f") // 6 Fractions of second, one digit dt.ToString("s^f") // 32^6 Seconds and fractions of second, one digit dt.ToString("ff") // 60 Fractions of second, two digits dt.ToString("fff") // 609 Fractions of second, three digits dt.ToString("ffff") // 6093 Fractions of second, four digits dt.ToString("fffff") // 60937 Fractions of second, five digits dt.ToString("ffffff") // 609375 Fractions of second, six digits dt.ToString("fffffff") // 6093750 Fractions of second, seven digits dt.ToString("g") // 8/18/2009 10:34 PM General dt.ToString("%g") // A.D. Era (eg. A.D.) dt.ToString("y-g") // 9-A.D. Year and era (eg. 5-A.D.) dt.ToString("gg") // A.D. Era (eg. A.D.) dt.ToString("%h") // 10 Hour (1-12) dt.ToString("h-m") // 10-34 Hour and minute dt.ToString("hh") // 10 Hour (01-12) dt.ToString("HH") // 22 Hour (00-23) dt.ToString("m") // August 18 Month name and date dt.ToString("%m") // 34 Minute (0-59) dt.ToString("hh_m") // 10_34 Hour and minute (0-59) dt.ToString("mm") // 34 Minute (00-59) dt.ToString("M") // August 18 Month name and date dt.ToString("%M") // 8 Month number (1-12) dt.ToString("M+d") // 8+18 Month number and day number dt.ToString("MM") // 08 Month number (01-12) dt.ToString("MMM") // Aug Month abbreviation dt.ToString("MMMM") // August Month name dt.ToString("s") // 2009-08-18T22:34:32 Standard sortable date/time dt.ToString("%s") // 32 Seconds (0-59) dt.ToString("s^ff") // 32^60 Seconds (0-59) and fraction of seconds dt.ToString("ss") // 32 Seconds (00-59) dt.ToString("t") // 10:34 PM Long time dt.ToString("%t") // P First letter of AM/PM designator dt.ToString("hh+t") // 10+P Hour and first letter of AM/PM designator dt.ToString("tt") // PM AM/PM designator dt.ToString("y") // August, 2009 ShortDate dt.ToString("m-y") // 34-9 Month and year dt.ToString("yy") // 09 Year (00-99) dt.ToString("yyyy") // 2009 Year (0000-9999) dt.ToString("%z") // -5 Whole hour time zone (-12 to +13) dt.ToString("Zone:z") // Zone:-5 Zone - and whole hour time zone (-12 to +13) dt.ToString("zz") // -05 Whole hour time zone (-12 to +13) with two digits dt.ToString("zzz") // -05:00 Time zone in hours and minutes
Standard DateTime Methods --------------------------------------------------------------------------------- DateTime.Now.Date // 8/18/2009 12:00:00 AM DateTime.Now.Day // 18 DateTime.Now.DayOfWeek // Tuesday DateTime.Now.Hour // 22 DateTime.Now.IsDaylightSavingTime() // True DateTime.Now.Kind // Local DateTime.Now.Millisecond // 609 DateTime.Now.Minute // 34 DateTime.Now.Month // 8 DateTime.Now.Second // 32 DateTime.Now.Ticks // 633862316726093750 DateTime.Now.TimeOfDay // 22:34:32.6093750 DateTime.Now.ToFileTime() // 128951264726093750 DateTime.Now.ToFileTimeUtc() // 128951264726093750 DateTime.Now.ToLocalTime() // 8/18/2009 10:34:32 PM DateTime.Now.ToLongDateString() // Tuesday, August 18, 2009 DateTime.Now.ToLongTimeString() // 10:34:32 PM DateTime.Now.ToOADate() // 40043.9406551968 DateTime.Now.ToShortDateString() // 8/18/2009 DateTime.Now.ToShortTimeString() // 10:34 PM DateTime.Now.ToUniversalTime() // 8/19/2009 3:34:32 AM DateTime.Now.Year // 2009
How install and configure
CruiseControl.NET
- Required system design,
software and downloads - Install and Configure NAnt
- Install and Build Cruise
Control server
The Cruise Control (Build) server must
be install on computer that can be accessed by all parties. This
is usually a development or test web server. Cruise Control can
be access internally or externally via web application.
Required
Software and Downloads
- ASP.NET -enabled web server
(typically IIS with ASP.NET configured) - Build Server - Microsoft .NET Framework
Version 2.0 - and any other version
the .NET Framework that the projects use - NAnt - Latest version
- NAntContrib - Latest version
- Download CruiseControl.NET
- CruiseControl.NET is distributed
in 3 formats - all that is necessary is the installers for CruiseControl.NET
proper (the Server and Web Dashboard) - CruiseControl.NET-(version)-
Setup.exe
Install and Configure
Build Server
- Log into the Web Server
that will host the CruiseControl build server as administrator - Install NAnt
- Download the binary distribution
archive. Either nant-bin.zip or nant-bin.tar.gz will work, the contents
of each archive are the same. - Remove any previous versions
of NAnt you may have installed. - Extract the contents of
the archive to the location you wish to install NAnt (eg: C:\Program
Files\NAnt in windows, or /usr/local/nant in Linux) - Depending on your environment,
create a wrapper script to run NAnt: - Run NAnt using Microsoft.NET
- Create a file called nant.bat in a directory that is included in the PATH system environment variable. (i.e. C:\WINDOWS).
- Add the following to nant.bat:
@echo off
"C:\Program Files\NAnt\bin\NAnt.exe" %*
- Open a new command prompt
(shell) and type nant
-help. If successful, you
should see a usage message displaying available command line options. - Install NAntContrib.
- Download the binary distribution
archive nantcontrib-0.85-bin.zip. - Extract the contents of
the archive to any location you wish. - After extract the content,
open the bin file and copy all of the contents in this
folder and paste them into the bin folder of the NAnt application. - Create a Build Directory
on this server: i.e. "D:\Build" - Then add the following directory
structure to this directory:
"D:\Build\CCNET"
"D:\Build\CCNET\Artifact"
"D:\Build\CCNET\Working"
"D:\Build\Source\[Project name]" - this will contain the exact
structure as the project
i.e. "import", "libs", "projects", "solutions",
"tools"
Install and Build CruiseControl.NET
- Install CruiseControl.NET
server - CruiseControl will install
the server application in the Program Files directory as well as install
a Web Site dashboard in IIS.
Note: Make sure the dash board is set as a web site and not as a virtual
folder. The only change that would need to be made if creating
a web site manually is setting the port number to something other than
80, i.e. 8090 - Open the ccnet.config file
in " C:\Program Files\CruiseControl.NET\server" and modify
it to point to projects specific information. This config file
may contain as many project tags as you wish. Here is an example
of the CMIS project config to work with VSS:
<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<project name="Cmis">
<triggers>
<intervalTrigger seconds="60" name="continuous"
/>
<
<workingDirectory>
<
<sourcecontrol type="vss" autoGetSource="false">
<executable>
<project>$/
<username>
<password>
</sourcecontrol>
<tasks>
<nant>
<
<
<
<
<
</
<
</nant>
</tasks>
<publishers>
<xmllogger>
<
</xmllogger>
</publishers>
</project>
</cruisecontrol>
- Create a file named [ProjectName].build
in the "D:\Build" folder
Here is an example of the cmis.build file:
?>
<project
name="Cmis" xmlns="http://nant.sf.net/
default="build">
<if test="${file::exists('build.
<echo message="Loading
Build Properties..." />
<include buildfile="build.properties.
/>
</if>
<target
name="getcurrent">
<echo message="Cleaning source... ${dir.source}"/>
<delete if="${directory::exists(dir.
dir="${dir.source}" />
- <echo message="Getting
source..."/>
username="${
password="${
localpath="$
recursive="
replace="
writable="
dbpath="${
path="${vss.
</target>
<target name="buildcurrent">
<echo message="Building
Cmis..."/>
<exec program="C:\WINDOWS\Microsoft.
commandline='"${dir.
/p:Configuration=Release /nologo' verbose="false" />
</target>
<target
name="package">
<echo message="Cleaning package...
${dir.package}"/>
<delete if="${directory::exists(dir.
dir="${dir.package}" />
<echo message="Creating Web Package..."/>
<copy if="${directory::exists(dir.
todir="${dir.package.web}">
<fileset refid="files.web"/>
</copy>
<echo message="Creating Admin Package..."/>
<copy if="${directory::exists(dir.
todir="${dir.package.web.
<fileset refid="files.web.admin"/>
</copy>
<echo message="Creating Service Package..."/>
<copy if="${directory::exists(dir.
todir="${dir.package.web.
<fileset refid="files.web.service"/>
</copy>
<echo message="Creating Reports Package..."/>
<copy if="${directory::exists(dir.
todir="${dir.package.web.
<fileset refid="files.web.reports"/>
</copy>
</target>
<target
name="build">
<call target="getcurrent"></call>
<call target="buildcurrent"></call>
</target>
<target name="label">
<echo message="Creating VSS Label '${project.version}'..."/>
<vsslabel
dbpath="${
path="${vss.
username="${
password="${
label="${
</target>
<target
name="release">
<call target="build"></call>
<call target="package"></call>
<call target="label"></call>
</target>
</project>
- In the same folder
create an xml file [ProjectName].properties.xml
Here is the cmis.properties.xml example:
<?xml version="1.0"
?>
<project
xmlns="http://nant.sf.net/
name="setproperties">
<!--
Project -->
<property name="project.name" value="Cmis"
/>
<property name="project.version" value="Beta v9.8.18.0"
/>
<!--
VSS -->
<property name="vss.db" value="D:\VSS\srcsafe.ini"
/>
<property name="vss.username" value="BuildMaster"
/>
<property name="vss.password" value="BuildMaster"
/>
<property name="vss.path" value="$/Cmis/Source"
/>
<!--
Paths -->
<property name="dir.root" value="D:\Build"
/>
<property name="dir.source" value="${dir.root}\Source"
/>
<property name="dir.package" value="${dir.root}\Package"
/>
<property name="dir.package.web" value="${dir.package}\Web"
/> <property name="dir.package.web.admin" value="${dir.package.web}\
<property name="dir.package.web.service" value="${dir.package}\Service"
/>
<property name="dir.package.web.reports" value="${dir.package}\Reports"
/>
<!--
Filesets -->
<fileset id="files.web" basedir="${dir.source}\
<include name="**/*"
/>
<exclude name="**/*.vbproj"
/>
<exclude name="**/*.vb"
/>
<exclude name="**/*.vspscc"
/>
<exclude name="**/*.scc"
/>
<exclude name="**/Controllers/**"
/>
<exclude name="**/Models/**"
/>
<exclude name="**/obj/**"
/>
<exclude name="**/Properties/**"
/>
</fileset>
<fileset id="files.web.admin" basedir="${dir.source}\
<include name="**/*"
/>
<exclude name="**/*.vbproj"
/>
<exclude name="**/*.vb"
/>
<exclude name="**/*.vspscc"
/>
<exclude name="**/*.scc"
/>
<exclude name="**/Controllers/**"
/>
<exclude name="**/Models/**"
/>
<exclude name="**/obj/**"
/>
<exclude name="**/Properties/**"
/>
</fileset>
<fileset id="files.web.service" basedir="${dir.source}\
<include name="**/*"
/>
<exclude name="**/*.vbproj"
/>
<exclude name="**/*.vb"
/>
<exclude name="**/*.vspscc"
/>
<exclude name="**/*.scc"
/>
<exclude name="**/Controllers/**"
/>
<exclude name="**/Models/**"
/>
<exclude name="**/obj/**"
/>
<exclude name="**/Properties/**"
/>
</fileset>
<fileset id="files.web.reports" basedir="${dir.source}\
<include name="**/*"
/>
<exclude name="**/*.vbproj"
/>
<exclude name="**/*.vb"
/>
<exclude name="**/*.vspscc"
/>
<exclude name="**/*.scc"
/>
<exclude name="**/Controllers/**"
/>
<exclude name="**/Models/**"
/>
<exclude name="**/obj/**"
/>
<exclude name="**/Properties/**"
/>
</fileset>
</project>
Creating a centered page layout with CSS
CSS Menu Tabs
CSS Rounded Box Generator
CSS2 Reference
Performs conditional processing in batch programs.
- IF [NOT] ERRORLEVEL number (command) [ELSE command]
- IF [NOT] string1==string2 (command) [ELSE command]
- IF [NOT] EXIST filename (command) [ELSE command]
NOT | Specifies that Windows should carry out the command only if the condition is false. |
ERRORLEVEL number | Specifies a true condition if the last program run returned an exit code equal to or greater than the number specified. |
command | Specifies the command to carry out if the condition is met. |
string1==string2 | Specifies a true condition if the specified text strings match. |
EXIST filename | Specifies a true condition if the specified filename exists. |
IF EXIST filename. (del filename.) ELSE (echo filename. missing) IF EXIST filename. ( del filename. ) ELSE ( echo filename. missing )
Applying this solution using Excel 2007 will allow you to insert or delete rows (or columns) without having to reformat them.
Each time you insert, the rows/columns after the insert point will flip colors.
- Select the color for every EVEN row or column:
- Highlight the rows you want to apply the formatting pattern to.
- From the Format menu, select Conditional Formatting.
- In the Conditional Formatting window, select Format is from the drop down menu.
- Enter this formula:
- For alternating row colors: =mod(row(),2)=1
- For alternating column colors: =mod(column(),2)=1
- From the Format Cells window, select the Patterns tab.
Select the color you would like to apply to the 2nd, 4th, 6th, etc. rows or columns. - Click OK
- Select the color for every ODD row or column:
- Repeat step 1-3 above.
- Enter this formula:
- For alternating row colors: =mod(row(),2)=0
- For alternating column colors: =mod(column(),2)=0
- From the Format Cells window, select the Patterns tab.
Select the color you would like to apply to the 1st, 3rd, 5th, etc. rows or columns. - Click OK
Describe here.
<script language="JavaScript" type="text/javascript"> <!-- function ShowHide(element) { if (document.getElementById(element).style.display == 'block') { document.getElementById(element).style.display = 'none'; } else { //if (document.getElementById(element).style.width > 650) { // document.getElementById(element).style.maxWidth = "100%"; //} document.getElementById(element).style.display = 'block'; } } --> </script> <p onclick="ShowHide('Div1');" onmouseover="this.style.cursor='pointer'" class="Title" title="Expand">This is the Title. Click me for a description.</p> <div id="Div1" style="display:none;" > <p class="Text">This is the description that displays or hides when the Title paragraph is clicked.</p> </div>
MSDN: LINQ To SQL Samples
MSDN Data Platform Development
return (from xfs in dc.tblXRefFrameSpecifications join frame in dc.tblFrames on xfs.uiFrameFK equals frame.uiFramePK join framecolor in dc.tblFrameColors on xfs.uiFrameColorFK equals framecolor.uiFrameColorPK join frametype in dc.tblFrameTypes on xfs.uiFrameTypeFK equals frametype.uiFrameTypePK join lensmaterial in dc.tblLensMaterials on xfs.uiLensMaterialFK equals lensmaterial.uiLensMaterialPK join lenstype in dc.tblLensTypes on xfs.uiLensTypeFK equals lenstype.uiLensTypePK join temple in dc.tblTemples on xfs.uiTempleFK equals temple.uiTemplePK select new XrefFrameSpecs { XRefFrameSpecificationGUID = xfs.uiXRefFrameSpecificationPK.ToString(), FrameType = frametype.vcFrameTypeDescription, LensMaterial = lensmaterial.vcDescription, LensType = lenstype.vcLensTypeDescription, Temple = temple.vcTempleDescription, FrameDescription = frame.vcFrameDescription, FrameColor = framecolor.vcFrameColor, BridgeSize = xfs.vcBridgeSize, EyeSize = xfs.vcEyeSize //}).ToList(); }).Where(pc => pc.BridgeSize.Equals("24")).Where(pc => pc.EyeSize.Equals("52")).ToList();
Insert Example using (SecurityDataContext dc = new SecurityDataContext()) { tblSecurity_AuthorizedUser newUser = new tblSecurity_AuthorizedUser(); newUser.bIsActive = true; newUser.SSN = "123456789"; dc.tblSecurity_AuthorizedUsers.InsertOnSubmit(newUser); dc.SubmitChanges(); }
Update Example using (SecurityDataContext dc = new SecurityDataContext()) { var thisUser = (from p in dc.tblSecurity_AuthorizedUsers select p).First(); thisUser.bIsActive = false; dc.SubmitChanges(); }
Delete Example using (SecurityDataContext dc = new SecurityDataContext()) { var thisUser = (from p in dc.tblSecurity_AuthorizedUsers where p.SSN.Equals("123456789") select p).First(); dc.tblSecurity_AuthorizedUsers.DeleteOnSubmit(thisUser); dc.SubmitChanges(); }
// Create a Base Query var WorkloadCCRFromDB = (from p in dc.tblWorkloadCCRs select p) // Not Executed Yet // Add a Where Clause to the query WorkloadCCRFromDB = WorkloadCCRFromDB.Where(pc => pc.iWorkloadCCRPK.Equals([WorkLoadCCRPK type value)]); // still not executed yet // Add another Where Clause to the query WorkloadCCRFromDB = WorkloadCCRFromDB.Where(pc => pc.fieldname2.Equals([FieldName2 type value)]); // still not executed yet // Execution of the query is delayed until an evaluation must be made // on the dynamic contents of the results of the query if (WorkloadCCRFromDB.Any()) // .Any() Method actually Executes the query and evaluates .Any() condition return WorkloadCCRFromDB;
Dim dc As New CMISNightlyProcessingDataContext
'SELECT MT.*, LEFT(CNA.zip, 5) As ZipCode
'FROM Medicaid_Transactions MT
'INNER JOIN Client_NameAddress CNA ON MT.PK_Client = CNA.PK_Client
'WHERE TransCode <> 'D'
' AND CNA.NameType = 1
Dim MedicaidTransactions = (From mt In dc.Medicaid_Transactions _
Join cna In dc.Client_NameAddresses On mt.PK_CLIENT Equals cna.PK_Client _
Where (Not mt.TransCode.Equals("D"c)) And cna.NameType = 1 _
Let ZipCode = Left(cna.ZIP, 5) _
Select mt, ZipCode)
If Not MedicaidTransactions.Any() Then
UtilityLibrary.LogToAutoProcessingLogDetails("No Medicaid Transaction Records to Process. Nothing to do.")
Else
UtilityLibrary.LogToAutoProcessingLogDetails(String.Format("{0} Total Medicaid_Transactions records need to be processed.", MedicaidTransactions.Count()))
End If
For Each MT In MedicaidTransactions
Console.WriteLine("Case: " & MT.mt.Case)
Console.WriteLine("ZipCode: " & MT.ZipCode)
Next
Listing 1 ' The code block below will fail because of an apparent LINQ bug that doesn't interpret ' the CHAR values in ValidBeginCodes array as a value in the SQL statement that needs single quotes. Dim ValidBeginCodes As Char() = {"P"c, "M"c} Dim dc As New CMISNightlyProcessingDataContext() Dim CFR = (From p In dc.Client_FinancialRestrictions _ Where p.PK_Financial = PKFinancial _ And ValidBeginCodes.Contains(p.BeginCode) _ And p.ActiveDate.HasValue() _ And Not p.EndDate.HasValue() _ Select p) SELECT [t0].[PK_Financial], [t0].[RecordKey], [t0].[BeginCode], [t0].[EnteredDate], [t0].[ActiveDate], [t0].[EndDate], [t0].[EndCode], [t0].[RecordLocked], [t0].[CreatedBy], [t0].[CreatedWhen], [t0].[PrevUpdatedBy], [t0].[PrevUpdatedWhen], [t0].[CHANGEDBY], [t0].[CHANGEDWHEN], [t0].[ClientFinancialRestrictionsID] FROM [dbo].[Client_FinancialRestrictions] AS [t0] WHERE ([t0].[PK_Financial] = 289848) AND (([t0].[BeginCode]) IN (P, M)) AND ([t0].[ActiveDate] IS NOT NULL) AND (NOT ([t0].[EndDate] IS NOT NULL))
Listing 2 ' Changing the array type to String allows LINQ to create the proper SQL statement. Dim ValidBeginCodes As String() = {"P", "M"} Dim dc As New CMISNightlyProcessingDataContext() Dim CFR = (From p In dc.Client_FinancialRestrictions _ Where p.PK_Financial = PKFinancial _ And ValidBeginCodes.Contains(p.BeginCode) _ And p.ActiveDate.HasValue() _ And Not p.EndDate.HasValue() _ Select p) SELECT [t0].[PK_Financial], [t0].[RecordKey], [t0].[BeginCode], [t0].[EnteredDate], [t0].[ActiveDate], [t0].[EndDate], [t0].[EndCode], [t0].[RecordLocked], [t0].[CreatedBy], [t0].[CreatedWhen], [t0].[PrevUpdatedBy], [t0].[PrevUpdatedWhen], [t0].[CHANGEDBY], [t0].[CHANGEDWHEN], [t0].[ClientFinancialRestrictionsID] FROM [dbo].[Client_FinancialRestrictions] AS [t0] WHERE ([t0].[PK_Financial] = 261875) AND ((CONVERT(NVarChar(1),CONVERT(NChar(1),[t0].[BeginCode]))) IN ('P', 'M')) AND ([t0].[ActiveDate] IS NOT NULL) AND (NOT ([t0].[EndDate] IS NOT NULL))
LINQ Error: String must be exactly one character long.
When working with Linq, you may get the following error:
String must be exactly one character long.
The problem is in the Linq to SQL designer, and the way the code generator
interpreted results from the table/view being used. This is a bug in
the Linq generator that converts the Database TYPE nVarChar(1) or VarChar(1)
to Linq CHAR(1) in the ???.designer.vb of the ???.dbml file. It occurs ,
specifically, because the nVarChar(1) field allows String.Empty ("") to be
stored in it but a CHAR(1) field does not. When the linq query executes,
the String.Empty value from the database cannot be populated in the correlating
CHAR(1) Linq Property.
To remedy this, go back to the designer (open the ???.dbml file), pin the
Properties sidebar open, and look at the elements which have been mapped.
Any one which is mapped to Char(1) should be changed to a String.
Notes: This may impact table relationships (constrained on the field in
question) AND stored procedures that return a table type (such as Appl_Financial)
instead of an (Auto-generated Type). In the case where the change has
these side-effects it may be necessary to either:
1. Leave the Linq alone in the .dbml and the designer.vb and use the
Linq conversion of Varchar(1) to CHAR(1) and deal with the differences
in your code.
2. Re-design your database to use CHAR(1) types instead of nVarChar(1)
and ensure there is exactly one character in the data field in
the table in question. Then delete and re-add the table to the
.dbml file. If you need to have a one character field, then
your database should have been designed with a CHAR(1) database type
initially. This is the PREFERRED solution if you need to have a CHAR(1).
If there are foreign constraints on this field, you will have to
delete them and re-build them. If there are indexes on this field
you may have to delete and re-build them as well.
3. Re-design your database and convert nVarChar(1) to nVarChar(2).
Then delete and re-add the table to the .dbml file. This is NOT
the PREFERRED solution becuase future development or code
refactoring will have to "downsize" this field at a later date.
Since "downsizing" is much much harder to do than "upsizing", don't
implement this solution unless you are NOT going to be the future
developer. If there are foreign constraints on this field, you will
have to delete them and re-build them. If there are indexes on this
field you may have to delete and re-build them as well.
nUnit - Test Driven Development with NUnit
Quantity Pattern - The Money Object
MSDN: Exploring the Singleton Design Pattern
MSDN: Exploring the Factory Design Pattern
MSDN: Exploring the Observer Design Pattern
YODA: Implementing the Singleton Pattern in C#
Java (J2SE 5.0) and C# Comparison
static void Main(string[] args) { // Given three expressions... bool Expression1 = true; bool Expression2 = true; bool Expression3 = true; /* You may run across code that looks something like this. * Using this type of construct has a bad smell, since the if/else shortcut has multiple expressions. */ bool x; x = (Expression1) ? ((Expression2) ? ((Expression3) ? true : false) : false) : false; Console.WriteLine(x); // Writes True /* By expanding it into if statements you can determine * where the common result, in this case "false" is found, and why. */ if (Expression1) if (Expression2) if (Expression3) x = true; else x = false; else x = false; else x = false; Console.WriteLine(x); // Writes True /* Since x is only set to True when all three expressions are true, * the code can be refactored as follows: */ x = false; if (Expression1 && Expression2 && Expression3) x = true; Console.WriteLine(x); // Writes True // Now, you can refactor the code so that it makes better sense. x = (Expression1 && Expression2 && Expression3) ? true : false; Console.WriteLine(x); // Writes True }
Problem: You have a temp that is assigned to once with a simple expression, and the temp is getting in the way of other refactorings.
Solution: Replace all references to that temp with the expression.
double basePrice = anOrder.basePrice(); return (basePrice > 1000)
V
return (anOrder.basePrice() > 1000)
C# Regex.Match Examples
Regular-Expressions.info
Wiki: Regular expressions
Regular Expressions found in Toadlib
/// <summary> /// Tested and working with 4631189780, 463-118-9780, (579).293-3763, (560) 879.3837 /// </summary> public const string TenDigitPhoneNumberPattern = "^\\(?([1-9]\\d{2})\\)?\\D*?([1-9]\\d{2})\\D*?(\\d{4})$"; /// <summary> /// Match a North American phone number with an optional area code and an optional "-" /// character to be used in the phone number and no extension /// </summary> public const string NorthAmericanPhoneNumberPattern = "^(\\(?[0-9]{3}\\)?)?\\-?[0-9]{3}\\-?[0-9]{4}$"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string EmailAddressPattern = "\\A[A-Z0-9._%-]+@[A-Z0-9._%-]+\\.[A-Z]{2,4}\\z"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string ShortDatePattern = "^([0-9]{1,2})/([0-9]{1,2})/([0-9]{4,4})$"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string UppercaseAndLowercaseAlphaPattern = "[^a-zA-Z]"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string UppercaseAlphaPattern = "^[A-Z]*$"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string AlphaNumericPattern = "[^a-zA-Z0-9]"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string WebSiteAddressPattern = "(([a-zA-Z][0-9a-zA-Z+\\-\\.]*:)?/{0,2}[0-9a-zA-Z;/?:@&=+$\\.\\-_!~*'()%]+)?(#[0-9a-zA-Z;/?:@&=+$\\.\\-_!~*'()%]+)?"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string SocialSecurityNumberPattern = "^((?!000)([0-6]\\d{2}|[0-7]{2}[0-2]))-((?!00)\\d{2})-((?!0000)\\d{4})$"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string NotIntegerPattern = "[^0-9-]"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string IntegerPattern = "^-[0-9]+$|^[0-9]+$"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string NotWholeNumberPattern = "[^0-9]"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string NatualNumberPattern = "0*[1-9][0-9]*"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string NotPositiveNumberPattern = "[^0-9.]"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string PositiveNumberPattern = "^[.][0-9]+$|[0-9]*[.]*[0-9]+$"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string TwoDotPattern = "[0-9]*[.][0-9]*[.][0-9]*"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string TwoMinusPattern = "[0-9]*[-][0-9]*[-][0-9]*"; /// <summary> /// Tested and working with --- (Needs examples) /// </summary> public const string ValidNumberPattern = "(^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$)|(^([-]|[0-9])[0-9]*$)"; /// <summary> /// Tested. matches with with "00000" or "09090-0000" or "000000000" /// </summary> public const string ValidZipCode = "^\\d{5}$|^\\d{5}-\\d{4}$|^\\d{9}$"; /// <summary> /// Tested. matches with "0000" /// </summary> public const string ValidZipCodePlus4 = "^\\d{4}$";
In the c languange you can use sscanf(), but there is no function similar to this in .NET.
The equivalent function is to use Regex to map fixed length field sizes to a GROUP, then access the GROUP NAMES to get the values.
// Create the pattern using Regex.
// <KEY> is a GROUP.
// ".{22}" means any (.) 22 characters {22}.
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}", @"^");
sb.AppendFormat("{0}", @"(?<KEY>.{22})");
sb.AppendFormat("{0}", @"(?<ORDERNUM>.{7})");
sb.AppendFormat("{0}", @"(?<SSN>.{9})");
sb.AppendFormat("{0}", @"(?<D_ORD>.{8})");
sb.AppendFormat("{0}", @"(?<D_RX>.{8})");
sb.AppendFormat("{0}", @"(?<INITIALS>.{3})");
sb.AppendFormat("{0}", @"(?<PRIORITY>.{1})");
string pattern = sb.ToString();
int OrderSequence = 0;
using (StreamReader sr = new StreamReader(this.FileNamePathToProcess))
{
Regex re = new Regex(pattern);
while (!sr.EndOfStream)
{
Match ma = re.Match(sr.ReadLine());
OrderData myOrderData = new OrderData();
myOrderData.OrderSequence = ++OrderSequence;
myOrderData.OrderKey = ma.Groups["KEY"].Value.TrimEnd();
myOrderData.OrderNumber = ma.Groups["ORDERNUM"].Value.TrimEnd();
myOrderData.PatientSocialSecurity = ma.Groups["SSN"].Value.TrimEnd();
myOrderData.D_ORD = ma.Groups["D_ORD"].Value.TrimEnd();
myOrderData.D_RX = ma.Groups["D_RX"].Value.TrimEnd();
myOrderData.OrderTechnicianInitials = ma.Groups["INITIALS"].Value.TrimEnd();
myOrderData.OrderPriority = ma.Groups["PRIORITY"].Value.TrimEnd();
this.PackageOrderData.Add(myOrderData);
}
}
Introduction.
The first step required to use CLR in SQL Server, whether it be for a user defined type,
user defined function or stored procedure, is to enable CLR fo the SQL instance.
To use TSQL to enable CLR for the instance:
EXEC SP_CONFIGURE 'show advanced options', '1' RECONFIGURE EXEC SP_CONFIGURE 'clr enabled', '1' RECONFIGURE
Then you will need to validate that the specific database that you plan to use CLR in is at 90 compatibility mode or higher (SQL 2008 will be 100).
To determine your current compatibility level execute the following command:
--EXEC sp_helpdb '[DATABASE NAME]' EXEC sp_helpdb 'SRTSIII'
If the compatibility level is 80 or less, you will need to execut the following TSQL to upgrade the database to 90 compatibility:
ALTER DATABASE SRTSIII SET SINGLE_USER EXEC sp_dbcmptlevel SRTSIII, 90 ALTER DATABASE SRTSIII SET MULTI_USER
How to stop the transaction log of a SQL Server database from growing unexpectedly
6 ways to import data into SQL Server
Introduction.
SQL Server allows you to draw diagrams of your schema.
These diagrams are stored in a binary format in dbo.[sysdiagrams]. That data is backed-up/restored with the actual database,
but there is NO SUPPORTED METHOD to save to a file. This is where ScriptDiagram2008 is used: to script the diagram data into an sql script.
Then you can save the script as a .sql file, and run it whenever you want to restore your database diagram.
This is extremely useful when performing various actions against your database that do not restore your diagrams.
It is also extremely useful if part of your required project documentation is a database schema diagram. Typically,
you have already established certain "DOMAIN" diagrams, where all of the tables and relationships for a specific DOMAIN
(such as Contacts, Orders, Patients, etc.). So you have more than one diagram.
Probably the most important benefit, to me at least, is this. Look, to recreate a diagram is pretty simple -
re-select the tables, and poof - it's done. Or is it? Darnet, my original diagram was set up to print on 2 pages,
with specific locations of each table that made it intuitive to me how the tables were related, where relationsip
links (lines) did NOT go BEHIND other tables, overlap on top of each other, and minimized crossing each other.
Although it may be easy to "generally" re-create a diagram, once you've customized it for YOUR improved comprehension
it is nearly IMPOSSIBLE to re-create it exactly the same way - UNTIL NOW.
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'Tool_ScriptDiagram2008') BEGIN DROP PROCEDURE dbo.Tool_ScriptDiagram2008 END GO /** Author: Craig Dunn Description: Script Sql Server 2008 diagrams (inspired by usp_ScriptDatabaseDiagrams for Sql Server 2000 by Clay Beatty, and Tool_ScriptDiagram2005 by yours truly) Example: USE [YourDatabaseName] EXEC Tool_ScriptDiagram2008 'DiagramName' Where: @name is: Name of the diagram in the Sql Server database instance Helpful Articles: 1) Upload / Download to Sql 2005 http://staceyw.spaces.live.com/blog/cns!F4A38E96E598161E!404.entry 2) MSDN: Using Large-Value Data Types http://msdn2.microsoft.com/en-us/library/ms178158.aspx 3) "original" Script, Save, Export SQL 2000 Database Diagrams http://www.thescripts.com/forum/thread81534.html 4) SQL2008 'undocumented' sys.fn_varbintohexstr http://www.sqlservercentral.com/Forums/Topic664234-1496-1.aspx */ CREATE PROCEDURE [dbo].[Tool_ScriptDiagram2008] ( @name VARCHAR(128) ) AS BEGIN DECLARE @diagram_id INT DECLARE @index INT DECLARE @size INT DECLARE @chunk INT DECLARE @line VARCHAR(max) -- Set start index, and chunk 'constant' value SET @index = 1 -- SET @chunk = 32 -- values that work: 2, 6 -- values that fail: 15,16, 64 -- Get PK diagram_id using the diagram's name (which is what the user is familiar with) SELECT @diagram_id=diagram_id , @size = DATALENGTH(definition) FROM sysdiagrams WHERE [name] = @name IF @diagram_id IS NULL BEGIN PRINT '/**Diagram name [' + @name + '] could not be found. */' END ELSE -- Diagram exists BEGIN -- Now with the diagram_id, do all the work PRINT '/**' PRINT '' PRINT 'Restore diagram ''' + @name + '''' PRINT ' ' PRINT '' PRINT 'Generated by Tool_ScriptDiagram2008' PRINT 'Will attempt to create [sysdiagrams] table if it doesn''t already exist' PRINT ' ' PRINT '' + LEFT(CONVERT(VARCHAR(23), GETDATE(), 121), 16) + ' ' PRINT '*/' PRINT 'PRINT ''=== Tool_ScriptDiagram2008 restore diagram [' + @name + '] ===''' PRINT ' -- If the sysdiagrams table has not been created in this database, create it! IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''sysdiagrams'') BEGIN -- Create table script generated by Sql Server Management Studio -- _Assume_ this is roughly equivalent to what Sql Server/Management Studio -- creates the first time you add a diagram to a 2008 database CREATE TABLE [dbo].[sysdiagrams]( [name] [sysname] NOT NULL, [principal_id] [int] NOT NULL, [diagram_id] [int] IDENTITY(1,1) NOT NULL, [version] [int] NULL, [definition] [varbinary](max) NULL, PRIMARY KEY CLUSTERED ( [diagram_id] ASC )WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) , CONSTRAINT [UK_principal_name] UNIQUE NONCLUSTERED ( [principal_id] ASC, [name] ASC )WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ) EXEC sys.sp_addextendedproperty @name=N''microsoft_database_tools_support'', @value=1 , @level0type=N''SCHEMA'',@level0name=N''dbo'', @level1type=N''TABLE'',@level1name=N''sysdiagrams'' PRINT ''[sysdiagrams] table was created as it did not already exist'' END -- Target table will now exist, if it didn''t before' PRINT 'SET NOCOUNT ON -- Hide (1 row affected) messages' PRINT 'DECLARE @newid INT' PRINT 'DECLARE @DiagramSuffix varchar (50)' PRINT '' PRINT 'PRINT ''Suffix diagram name with date, to ensure uniqueness''' PRINT 'SET @DiagramSuffix = '' '' + LEFT(CONVERT(VARCHAR(23), GETDATE(), 121), 16)' PRINT '' PRINT 'PRINT ''Create row for new diagram''' -- Output the INSERT that _creates_ the diagram record, with a non-NULL [definition], -- important because .WRITE *cannot* be called against a NULL value (in the WHILE loop) -- so we insert 0x so that .WRITE has 'something' to append to... PRINT 'BEGIN TRY' PRINT ' PRINT ''Write diagram ' + @name + ' into new row (and get [diagram_id])''' SELECT @line = ' INSERT INTO sysdiagrams ([name], [principal_id], [version], [definition])' + ' VALUES (''' + [name] + '''+@DiagramSuffix, '+ CAST (principal_id AS VARCHAR(100))+', '+CAST (version AS VARCHAR(100))+', 0x)' FROM sysdiagrams WHERE diagram_id = @diagram_id PRINT @line PRINT ' SET @newid = SCOPE_IDENTITY()' PRINT 'END TRY' PRINT 'BEGIN CATCH' PRINT ' PRINT ''XxXxX '' + Error_Message() + '' XxXxX''' PRINT ' PRINT ''XxXxX END Tool_ScriptDiagram2008 - fix the error before running again XxXxX''' PRINT ' RETURN' PRINT 'END CATCH' PRINT '' PRINT 'PRINT ''Now add all the binary data...''' PRINT 'BEGIN TRY' WHILE @index < @size BEGIN -- Output as many UPDATE statements as required to append all the diagram binary -- data, represented as hexadecimal strings SELECT @line = ' UPDATE sysdiagrams SET [definition] .Write (' + ' ' + UPPER(sys.fn_varbintohexstr (SUBSTRING (definition, @index, @chunk))) + ', null, 0) WHERE diagram_id = @newid -- index:' + CAST(@index AS VARCHAR(100)) FROM sysdiagrams WHERE diagram_id = @diagram_id PRINT @line SET @index = @index + @chunk END PRINT '' PRINT ' PRINT ''=== Finished writing diagram id '' + CAST(@newid AS VARCHAR(100)) + '' ===''' PRINT ' PRINT ''=== Refresh your Databases-[DbName]-Database Diagrams to see the new diagram ===''' PRINT 'END TRY' PRINT 'BEGIN CATCH' PRINT ' -- If we got here, the [definition] updates didn''t complete, so delete the diagram row' PRINT ' -- (and hope it doesn''t fail!)' PRINT ' DELETE FROM sysdiagrams WHERE diagram_id = @newid' PRINT ' PRINT ''XxXxX '' + Error_Message() + '' XxXxX''' PRINT ' PRINT ''XxXxX END Tool_ScriptDiagram2008 - fix the error before running again XxXxX''' PRINT ' RETURN' PRINT 'END CATCH' END END GO
/* ============================================= Author: Gary Janecek Create date: 5/4/2010 Description: Recompiles ALL User Objects in the database. The first part of the code inserted the names of all stored procedures to a table variable, along with their schema names. The next part of the code inserted the names of all views to a table variable, along with their schema names. The next part of the code inserted the names of all user defined functions to a table variable, along with their schema names. A table variable is used just to avoid a CURSOR. The WHILE loop then reads each object name and passes it to the system stored procedure: sp_refreshsqlmodule. sp_refreshsqlmodule re-compiles the object and will throw an error if the validation fails. The CATCH block catches the error if the validation fails, and displays the error message in the output window. NOTE: Due to an unknown condition (so far) this script will fail on all objects AFTER A FAIL OCCURS. Fix the first object that failed and re-run this again to find the next problem. Repeat until all objects are fixed. Sample Call: EXEC aDBMaint_ReCompileAllDatabaseObjects ============================================= */ CREATE PROCEDURE [dbo].[aDBMaint_ReCompileAllDatabaseObjects] AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Insert statements for procedure here -- table variable to database object names. -- NOTE the IDENTITY FIELD so we don't need a CURSOR DECLARE @myListOfObjects TABLE (RowID INT IDENTITY(1,1) , ObjectName sysname , ObjectType varchar(max)) -- retrieve the list of stored porcedures INSERT INTO @myListOfObjects(ObjectName, ObjectType) SELECT '[' + s.[name] + '].[' + sp.name + ']' AS ObjectName, 'StoredProcedure' AS ObjectType FROM sys.procedures sp INNER JOIN sys.schemas s ON s.schema_id = sp.schema_id WHERE is_ms_shipped = 0 ORDER BY ObjectName -- retrieve the list of views INSERT INTO @myListOfObjects(ObjectName, ObjectType) SELECT '[' + s.[name] + '].[' + vw.name + ']' AS ObjectName, 'View' AS ObjectType FROM sys.views vw INNER JOIN sys.schemas s ON s.schema_id = vw.schema_id WHERE is_ms_shipped = 0 ORDER BY ObjectName -- retrieve the list of functions INSERT INTO @myListOfObjects(ObjectName, ObjectType) SELECT '[' + s.[name] + '].[' + func.name + ']' AS FunctionName, 'Function' AS ObjectType FROM sys.objects func INNER JOIN sys.schemas s ON s.schema_id = func.schema_id WHERE is_ms_shipped = 0 AND type_desc LIKE '%FUNCTION%' ORDER BY FunctionName -- counter variables DECLARE @RowNumber INT DECLARE @TotalRows INT SELECT @RowNumber = 1 SELECT @TotalRows = COUNT(*) FROM @myListOfObjects DECLARE @ThisObjectName sysname -- Start the loop WHILE @RowNumber < @TotalRows BEGIN SELECT @ThisObjectName = ObjectName FROM @myListOfObjects WHERE RowID = @RowNumber SELECT @ThisObjectType = ObjectType FROM @myListOfObjects WHERE RowID = @RowNumber PRINT N'Refreshing... ' + @ThisObjectType + SPACE(16-LEN(@ThisObjectType)) + ': ' + @ThisObjectName BEGIN TRY -- Refresh the Object EXEC sp_refreshsqlmodule @ThisObjectName END TRY BEGIN CATCH PRINT 'Validation failed for : ' + @ThisObjectName + ', Error:' + ERROR_MESSAGE() END CATCH SET @RowNumber = @RowNumber + 1 END END
-- NOTE the IDENTITY FIELD so we don't need a CURSOR DECLARE @myListOfStoredProcedures TABLE (RowID INT IDENTITY(1,1), StoredProcedureName sysname) -- retrieve the list of stored porcedures INSERT INTO @myListOfStoredProcedures(StoredProcedureName) SELECT '[' + s.[name] + '].[' + sp.name + ']' AS StoredProcedureName FROM sys.procedures sp INNER JOIN sys.schemas s ON s.schema_id = sp.schema_id WHERE is_ms_shipped = 0 ORDER BY StoredProcedureName -- counter variables DECLARE @RowNumber INT DECLARE @TotalRows INT SELECT @RowNumber = 1 SELECT @TotalRows = COUNT(*) FROM @myListOfStoredProcedures DECLARE @ThisStoredProcedureName sysname -- Start the loop WHILE @RowNumber < @TotalRows BEGIN SELECT @ThisStoredProcedureName = StoredProcedureName FROM @myListOfStoredProcedures WHERE RowID = @RowNumber PRINT N'' PRINT 'Refreshing... ' + @ThisStoredProcedureName + ' ---- Executing: EXEC sp_refreshsqlmodule ''' + @ThisStoredProcedureName + '''' BEGIN TRY -- Refresh the Stored Procedure EXEC sp_refreshsqlmodule @ThisStoredProcedureName END TRY BEGIN CATCH PRINT 'Validation failed for : ' + @ThisStoredProcedureName + ', Error:' + ERROR_MESSAGE() END CATCH SET @RowNumber = @RowNumber + 1 END
This Stored Procedure Returns the RowCount of all the tables in a datbaase. In addition, when two database names are provided, it will return the rowcount of all of the tables in both datbases AND the DELTA (difference) in the RowCount of the same table in both databases. It is very useful to compare the rowcounts of two databases with identical tables.
/* ============================================= Author: Gary Janecek Create date: 5/4/2010 Description: Gets the rowcount of all tables in the database two specified databases Sample Call: EXEC aDBMaint_GetTableRowCount 'SRTSDevOld', 'SRTSDevOldARCHIVE' EXEC aDBMaint_GetTableRowCount 'SRTSIII' ============================================= */ ALTER PROCEDURE [dbo].[aDBMaint_GetTableRowCount] @db1 varchar(max), @db2 varchar(max) = NULL AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Insert statements for procedure here -- table variable to database object names. -- NOTE the IDENTITY FIELD so we don't need a CURSOR DECLARE @myListOfObjects TABLE (RowID INT IDENTITY(1,1), ObjectName sysname, TableName VARCHAR(max), ObjectType varchar(max)) DECLARE @myListOfObjects2 TABLE (RowID INT IDENTITY(1,1), ObjectName sysname, TableName VARCHAR(max), ObjectType varchar(max)) DECLARE @ExeStatement nvarchar(max) --SET @db1 = N'SRTSDevOldARCHIVE' SET @ExeStatement = N'SELECT ''['' + s.[name] + ''].['' + sp.name + '']'' AS ObjectName, sp.name AS TableName, ''TABLE'' AS ObjectType FROM ' + @db1 + '.sys.tables sp INNER JOIN ' + @db1 + '.sys.schemas s ON s.schema_id = sp.schema_id WHERE is_ms_shipped = 0 ORDER BY ObjectName' -- retrieve the list of tables INSERT INTO @myListOfObjects(ObjectName, TableName, ObjectType) EXECUTE sp_executesql @ExeStatement DECLARE @numOfRows TABLE (tblName VARCHAR(Max), ROWSDb1 INT, ROWSDb2 INT) -- counter variables DECLARE @RowNumber INT DECLARE @TotalRows INT SELECT @RowNumber = 1 SELECT @TotalRows = COUNT(*) FROM @myListOfObjects DECLARE @ThisObjectName sysname DECLARE @ThisObjectType varchar(max) DECLARE @TableName VARCHAR(MAX) DECLARE @myTable TABLE ( NAME varchar(MAX) ,ROWS INT ,RESERVED varchar(MAX) ,DATA varchar(MAX) ,INDEX_SIZE varchar(MAX) ,UNUSED varchar(MAX) ) -- Start the loop WHILE @RowNumber < @TotalRows BEGIN SELECT @ThisObjectName = ObjectName FROM @myListOfObjects WHERE RowID = @RowNumber SELECT @ThisObjectType = ObjectType FROM @myListOfObjects WHERE RowID = @RowNumber INSERT @myTable EXEC sp_spaceused @ThisObjectName SET @RowNumber = @RowNumber + 1 END INSERT @numOfRows SELECT NAME, ROWS, 0 FROM @myTable IF @db2 IS NULL BEGIN SELECT tblName, ROWSDb1 FROM @numOfRows Order by ROWSDb1 DESC, tblName END ELSE BEGIN --SELECT * FROM @numOfRows --SET @db1 = N'SRTSDevOldARCHIVE' SET @ExeStatement = N'SELECT ''['' + s.[name] + ''].['' + sp.name + '']'' AS ObjectName, sp.name AS TableName, ''TABLE'' AS ObjectType FROM ' + @db1 + '.sys.tables sp INNER JOIN ' + @db1 + '.sys.schemas s ON s.schema_id = sp.schema_id WHERE is_ms_shipped = 0 ORDER BY ObjectName' -- retrieve the list of tables INSERT INTO @myListOfObjects2(ObjectName, TableName, ObjectType) EXECUTE sp_executesql @ExeStatement --INSERT INTO @myListOfObjects2(ObjectName, TableName, ObjectType) --SELECT -- '[' + s.[name] + '].[' + sp.name + ']' AS ObjectName, -- sp.name AS TableName, -- 'TABLE' AS ObjectType -- FROM SRTSDevOldARCHIVE.sys.tables sp -- INNER JOIN sys.schemas s ON s.schema_id = sp.schema_id -- WHERE is_ms_shipped = 0 -- ORDER BY ObjectName SET @RowNumber = 1 SET @TotalRows = (SELECT COUNT(*) FROM @myListOfObjects2) DELETE @myTable WHILE @RowNumber < @TotalRows BEGIN SET @ThisObjectName = (SELECT ObjectName FROM @myListOfObjects2 WHERE RowID = @RowNumber) SET @ThisObjectType = (SELECT ObjectType FROM @myListOfObjects2 WHERE RowID = @RowNumber ) SET @TableName = (SELECT TableName FROM @myListOfObjects2 WHERE RowID = @RowNumber) SET @ExeStatement = N'USE ' + @db2 + ';EXECUTE sp_spaceused ' + @TableName INSERT @myTable EXECUTE sp_executesql @ExeStatement UPDATE @numOfRows SET ROWSDb2 = (SELECT ROWS FROM @myTable) WHERE tblName = @TableName DELETE @myTable SET @RowNumber = @RowNumber + 1 END SELECT *, ROWSDb1 - ROWSDb2 AS Delta FROM @numOfRows Order by Delta DESC END END
Database Migration can be complicated and overwhelming. The thing to do here is to break it down into smaller steps. This strategy applies whether your database has 10 tables or 1000 tables to migrate. These thoughts apply only to importing INTO SQL Server. The first incliniation I had when I was faced with a Data Migration project was to begin writing scripts that move data from the SOURCE database schema into the DESTINATION database schema. Soon, however, I discovered I had pre-empted a major first step - that of analyzing the DATA in the SOURCE database for normalization.
The Strategy
- Ensure SOURCE database has normalized data. The first most important step is to ANALYZE the source database for normalization.
If it is NOT normalized, then normalize it FIRST. For example:
- Check any SOURCE database fields which ALLOW NULLS. If the associated destination database field
is set to NOT ALLOW NULLS, then a decision needs to be made. Either de-normalize the DESTINATION database or normalize
the SOURCE database. MY RECOMMENDATION: Normalize the SOURCE database by updating the NULLS with "Unknown", or something
similar that matches the datatype, that will guarantee there will be NO problem with the execution of the Migration Scripts.
- Check any SOURCE database fields which are DATE fields (especially BirthDate and DeathDate fields). In unnormalized SOURCE databases,
the DeathDate field can sometimes hold a "future" date (which is wrong) and something needs to be done to normalize it
before migrating the data to the DESTINATION database. The Birthdate field could also have some similar issues. In addition,
the Birthdate cannot be chronologically AFTER the DeathDate.
- Check any SOURCE database fields which ALLOW NULLS. If the associated destination database field
- Ensure DESTINATION database has designed for normalization. You see, as a responsible Database Designer, if the
database I'm migrating to is NOT configured properly for normalization, then I don't migrate anything until I get it designed
to enforce normalization properly. - Write SQL Scripts that move data from SOURCE database to DESTINATION. Without normalizing both the SOURCE and DESTINATION
databases first, you run the risk of your migration scripts failing when they encouter de-normalized data. If your scripts
fail for this reason, the tendency is to fix your migration scripts to handle the exception. This is a rabbit-hole that you
want to avoid. The correct thing to do is to re-analyze the SOURCE and DESTINATION databases for normalization and fix them
before running your migration script again.
-- Create a Temporary Table with two fields DECLARE @Temptable TABLE ( uiMyTempSiteFK uniqueidentifier, IdOrSequence int ) -- Insert some data into the temp table -- and set all values in the IdOrSequence column to zero (0) INSERT @Temptable SELECT Top 10 s.uiSitePK, -- uiMyTempSiteFK 0 -- IdOrSequence -- Set all to 0 for now From tblSite s SELECT * from @Temptable (10 row(s) affected) uiMyTempSiteFK IdOrSequence ------------------------------------ ------------ 028000EA-D600-4EF6-A488-00B2B8AE98E4 0 78DA3432-19D0-48A5-9E39-0243F4D31DBD 0 A0222923-945C-4C60-8AE4-04DD4DF21455 0 8217714B-B4B2-44AE-BAE0-09285C6D414A 0 992E1EC6-C442-4D89-B455-0A9141B79C7B 0 BA309EF5-B415-4BC5-92EE-0C20ADD4573D 0 329ACF5F-A8AC-4236-AB9B-12FAB72F5C28 0 768ACAC0-D9D2-4B74-8B19-15240A0A4396 0 800EB5C6-04BB-48D2-88F9-1654FE283DFD 0 AAAAD4D1-5174-4016-9804-17471809A2FA 0 (10 row(s) affected) -- Update the IdOrSequence field to an incremented value starting at 1 DECLARE @Sequence INT SET @Sequence = 0 UPDATE @Temptable SET @Sequence = IdOrSequence = @Sequence + 1 SELECT * from @Temptable (10 row(s) affected) (10 row(s) affected) uiMyTempSiteFK IdOrSequence ------------------------------------ ------------ 028000EA-D600-4EF6-A488-00B2B8AE98E4 1 78DA3432-19D0-48A5-9E39-0243F4D31DBD 2 A0222923-945C-4C60-8AE4-04DD4DF21455 3 8217714B-B4B2-44AE-BAE0-09285C6D414A 4 992E1EC6-C442-4D89-B455-0A9141B79C7B 5 BA309EF5-B415-4BC5-92EE-0C20ADD4573D 6 329ACF5F-A8AC-4236-AB9B-12FAB72F5C28 7 768ACAC0-D9D2-4B74-8B19-15240A0A4396 8 800EB5C6-04BB-48D2-88F9-1654FE283DFD 9 AAAAD4D1-5174-4016-9804-17471809A2FA 10 (10 row(s) affected)
If you copy all of the table's records to an archive table and then delete all the records in the source table, you might want to reseed the source table's identity column, so you can control the sequence. Use DBCC CHECKIDENT.
-- DBCC CHECKIDENT syntax
DBCC CHECKIDENT ( tablename [, [NORESEED | RESEED [, newreseedvalue]]] )
-- tblLogSeverityLevel (Table) listing i_LogSeverityLevelID vcSeverityDescription -------------------- -------------------------------------------------- 1 General Information 2 General Warning 3 General Critical 4 Program Fatal 5 Program Exception 6 Duplicate Order Exists 7 NonDuplicate Order Exists 8 General Summary 9 Order Resubmit Error 10 Order Resubmit Success 11 Order Received Error 12 Order Received Success 13 Old Clinic Desktop -- Create INSERT STATEMENTS for the table's data SELECT 'INSERT tblLogSeverityLevel VALUES (''' + vcSeverityDescription + ''')' From tblLogSeverityLevel INSERT tblLogSeverityLevel VALUES ('General Information') INSERT tblLogSeverityLevel VALUES ('General Warning') INSERT tblLogSeverityLevel VALUES ('General Critical') INSERT tblLogSeverityLevel VALUES ('Program Fatal') INSERT tblLogSeverityLevel VALUES ('Program Exception') INSERT tblLogSeverityLevel VALUES ('Duplicate Order Exists') INSERT tblLogSeverityLevel VALUES ('NonDuplicate Order Exists') INSERT tblLogSeverityLevel VALUES ('General Summary') INSERT tblLogSeverityLevel VALUES ('Order Resubmit Error') INSERT tblLogSeverityLevel VALUES ('Order Resubmit Success') INSERT tblLogSeverityLevel VALUES ('Order Received Error') INSERT tblLogSeverityLevel VALUES ('Order Received Success') INSERT tblLogSeverityLevel VALUES ('Old Clinic Desktop') (13 row(s) affected) -- Delete ALL the rows in the table DELETE tblLogSeverityLevel (13 row(s) affected) -- Delete ALL the rows in the table DBCC CHECKIDENT (tblLogSeverityLevel, RESEED, 0) Checking identity information: current identity value '13', current column value '0'. DBCC execution completed. If DBCC printed error messages, contact your system administrator. -- Modifity the INSERT STATEMENTS to Eliminate unwanted rows, and execute INSERT tblLogSeverityLevel VALUES ('General Information') INSERT tblLogSeverityLevel VALUES ('General Warning') INSERT tblLogSeverityLevel VALUES ('General Critical') INSERT tblLogSeverityLevel VALUES ('Program Fatal') INSERT tblLogSeverityLevel VALUES ('Program Exception') INSERT tblLogSeverityLevel VALUES ('General Summary') INSERT tblLogSeverityLevel VALUES ('Old Clinic Desktop') -- tblLogSeverityLevel (Table) listing i_LogSeverityLevelID vcSeverityDescription -------------------- -------------------------------------------------- 1 General Information 2 General Warning 3 General Critical 4 Program Fatal 5 Program Exception 6 General Summary 7 Old Clinic Desktop
Use "FOR XML AUTO" to automatically generate "attributed" XML. "Attributed" means the row tag (<fc ...) is generated from the table alias (fc) AND each field in the result is an "ATTRIBUTE" of the row.
SELECT fc.vcFrameColorCode, fc.vcFrameColor FROM tblFrameColor fc where fc.vcFrameColorCode = 'BLK' vcFrameColorCode vcFrameColor ---------------- -------------------------------------------------- BLK BLACK SELECT fc.vcFrameColorCode, fc.vcFrameColor FROM tblFrameColor fc where fc.vcFrameColorCode = 'BLK' FOR XML AUTO --Note in this output how the table alias (fc) is the --ELEMENT tag and the field names (such as vcFrameColorCode) --is an attribute of the ELEMENT! <fc vcFrameColorCode="BLK" vcFrameColor="BLACK" />
Use "FOR XML PATH(...), ROOT(...)" to automatically generate "XELEMENT" XML. "XELEMENT" means the row tag is an XELEMENT and each field in the result is an XELEMENT of the row.
To NEST XML, put the results of a FOR XML into a variable, and select the variable (@xml) in the select <COLUMN LIST> as in SELECT f.vcFrameCode, f.vcFrame, @xml FROM ...
-- DECLARE A variable of type xml DECLARE @xml xml -- DEFINE the value for the variable to be -- the XML results of a Query SET @xml = ( SELECT fc.vcFrameColorCode, fc.vcFrameColor FROM tblFrameColor fc where fc.vcFrameColorCode = 'BLK' FOR XML PATH('Color'), ROOT('FrameColor') ) SELECT @xml --Note in this output how the table alias (fc) to --indicate a row ELEMENT is NOT used --and has been replaced with the PATH name ('Color'). Note --also the field names (such as vcFrameColorCode) --is an ELEMENT (<vcFrameColorCode></vcFrameColorCode>) --of the of the row ELEMENT (<Color>...</Color>)! --Note also that the whole output has been wrapped in a ROOT --ELEMENT ROOT('FrameColor') specified --(<FrameColor>...</FrameColor>). <FrameColor> <Color> <vcFrameColorCode>BLK</vcFrameColorCode> <vcFrameColor>BLACK</vcFrameColor> </Color> </FrameColor> -- SELECT two fields from one table and NEST the -- @xml variable and output the XML results SELECT f.vcFrameCode, f.vcFrame, @xml FROM tblFrame f WHERE vcFrameCode = 'DUO' FOR XML PATH('Frame'), ROOT('FRAMES') --Note in this output how the ELEMENT <FrameColor> is nested in its --own ELEMENT within each <Frame> ELEMENT, and that the whole output --has been wrapped in a ROOT ELEMENT <FRAMES>...</FRAMES> --ROOT('FRAMES') specified. <FRAMES> <Frame> <vcFrameCode>DUO</vcFrameCode> <vcFrame>DUO (FOC)</vcFrame> <FrameColor> <Color> <vcFrameColorCode>BLK</vcFrameColorCode> <vcFrameColor>BLACK</vcFrameColor> </Color> </FrameColor> </Frame> <Frame> <vcFrameCode>DUO</vcFrameCode> <vcFrame>DUO (FOC)</vcFrame> <FrameColor> <Color> <vcFrameColorCode>BLK</vcFrameColorCode> <vcFrameColor>BLACK</vcFrameColor> </Color> </FrameColor> </Frame> <Frame> <vcFrameCode>DUO</vcFrameCode> <vcFrame>DUO (FOC)</vcFrame> <FrameColor> <Color> <vcFrameColorCode>BLK</vcFrameColorCode> <vcFrameColor>BLACK</vcFrameColor> </Color> </FrameColor> </Frame> </FRAMES>
/* ============================================= Author: Gary Janecek Create date: 7/26/2010 Description: Returns the names of stored procedures that have the @StringToSearch in the text of the stored procedure ============================================= */ CREATE PROCEDURE aUtility_FindTextInStoredProcedure ( @StringToSearch varchar(max) ) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; SET @StringToSearch = '%' + @StringToSearch + '%' SELECT Distinct SO.Name FROM sysobjects SO (NOLOCK) INNER JOIN syscomments SC (NOLOCK) ON SO.id = SC.id AND SO.type = 'P' AND SC.text LIKE @StringToSearch ORDER BY SO.NAME END GO
Once, I had to come up with a way to have a stored procedure perform some function on a group of records in a table. I needed this because I had a Windows Forms application, that accessed my web service, that accessed ONLY stored procedures in the database. In fact, the ONLY method provided to access data in the database had to be ONLY through stored procedures. If I could have accessed the tables directly, I could have used Linq-to-SQL to pass the 'Serialized' list from my app, to the web service, and directly into the table. But since I have to go in through stored procedures only, the challenge was different.
The problem I had was that Stored Procedures do not take 'Lists' as parameters!
I could easily have written an SP that took each field of the table as a parameter, found that unique row and performed some action on it, but that would work on only one row in the table. I would have to invoke this SP (from my app, through the service, into the SP, result from the SP back to the service, and then back to the app) as an APP-to-DB round trip FOR EACH row my app had to perform (CRUD).
How could I do it to a group of records in the table?
XML! Although there are many other solutions I investigated (such as using SQL CLR), I found the easiest to understand and the quickest to implement - which was still highly reliable - was XML! The strategy: use my c# WinForms app to convert a LIST to and XML document (i.e. just a String), and pass it to the Service as a String parameter, then the Service calls the Stored Procedure with a varchar(max) parameter. Then, the Stored Procedure parses the varchar(max) parameter from XML into a temp table. Now that it's in a Table format in SQL, all SQL commands can use the data to perform whatever is needed.
var mySites = SomeListOfSites.ToList(); System.Xml.Linq.XElement xml = new System.Xml.Linq.XElement("ROOT", from p in mySites select new XElement("tblWorkloadCCRClinicToLabDetail", new XAttribute("uiSitePK", p.uiSitePK), new XAttribute("uiSiteTypeFK", p.uiSiteTypeFK), new XAttribute("vcSiteCode", p.vcSiteCode), new XAttribute("vcSiteDescription", p.vcSiteDescription)) ); --Sets the variable "xml" to the following XML: <ROOT> <tblWorkloadCCRClinicToLabDetail uiSitePK="ba309ef5-b415-4bc5-92ee-0c20add4573d" uiSiteTypeFK="6cc6e8d7-d8c2-46f2-b9e6-dd7c1be62785" vcSiteCode="000019" vcSiteDescription="MCAS BEAUFORT" /> <tblWorkloadCCRClinicToLabDetail uiSitePK="72211981-e737-4320-b014-40d18433a7d5" uiSiteTypeFK="6cc6e8d7-d8c2-46f2-b9e6-dd7c1be62785" vcSiteCode="001105" vcSiteDescription="Optometry Clinic, RACH" /> <tblWorkloadCCRClinicToLabDetail uiSitePK="1cd19421-01a8-4dbc-a982-43419d8ca153" uiSiteTypeFK="6cc6e8d7-d8c2-46f2-b9e6-dd7c1be62785" vcSiteCode="000010" vcSiteDescription="ATHENS OPTICAL CLINIC" /> <tblWorkloadCCRClinicToLabDetail uiSitePK="bafda1e1-9b8b-48ad-a36a-43ce24d585b1" uiSiteTypeFK="6cc6e8d7-d8c2-46f2-b9e6-dd7c1be62785" vcSiteCode="000023" vcSiteDescription="OPTOMETRY NAS BRUNSWICK" /> <tblWorkloadCCRClinicToLabDetail uiSitePK="fbf8953f-d151-48b1-82e5-4794a859fa16" uiSiteTypeFK="6cc6e8d7-d8c2-46f2-b9e6-dd7c1be62785" vcSiteCode="002049" vcSiteDescription="OPTOMETRY CLINIC" /> <tblWorkloadCCRClinicToLabDetail uiSitePK="0bf50929-eea7-4c83-9a32-53a96462c502" uiSiteTypeFK="6cc6e8d7-d8c2-46f2-b9e6-dd7c1be62785" vcSiteCode="000414" vcSiteDescription="2/9 BAS" /> </ROOT>
-- ============================================= -- Author: Gary Janecek -- Create date: 4/1/2010 -- Description: Updates the tblWorkloadCCRClinicToLabDetail table by DELETING all of the records -- matching the uiWorkloadCCRFK and INSERTING new records with the same uiWorkloadCCRFK -- that match the uiWorkloadCCRFK in the XML parameter received. -- SAMPLE CALL: --DECLARE @vcXML varchar(max) --SET @vcXML = '<ROOT> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="BA309EF5-B415-4BC5-92EE-0C20ADD4573D" iLabSequence="1" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="72211981-E737-4320-B014-40D18433A7D5" iLabSequence="2" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="1CD19421-01A8-4DBC-A982-43419D8CA153" iLabSequence="3" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="BAFDA1E1-9B8B-48AD-A36A-43CE24D585B1" iLabSequence="4" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="0BF50929-EEA7-4C83-9A32-53A96462C502" iLabSequence="6" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="BF2A1808-0821-4154-A3A7-648668263B31" iLabSequence="7" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="D5DC3071-BA01-4751-8D2E-8BBEAC1657E1" iLabSequence="8" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="E4367B7E-D89A-4BFD-A9E5-8E2C11E21BB3" iLabSequence="9" bIsRefundableLab="1" /> --<tblWorkloadCCRClinicToLabDetail uiWorkloadCCRFK="E403EDC2-3FEC-409D-840B-5F69B1257386" uiSiteClinicFK="028000EA-D600-4EF6-A488-00B2B8AE98E4" uiSiteLabFK="BFCE16C6-9DA9-4501-9391-95840BF08012" iLabSequence="10" bIsRefundableLab="1" /> --</ROOT>' --EXEC UpdateWorkloadCCRClinicToLabDetail @vcXML -- ============================================= CREATE PROCEDURE [dbo].[UpdateWorkloadCCRClinicToLabDetail] @vcXML varchar(max) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; BEGIN TRANSACTION DECLARE @idoc int -- Set up an internal table definition -- with SAME table structure as tblWorkloadCCRClinicToLabDetail DECLARE @myTable TABLE ( [uiWorkloadCCRFK] [uniqueidentifier] NOT NULL, [uiSiteClinicFK] [uniqueidentifier] NOT NULL, [uiSiteLabFK] [uniqueidentifier] NOT NULL, [iLabSequence] [int] NOT NULL, [bIsRefundableLab] [bit] NOT NULL ) --Create an internal representation of the XML document. EXEC sp_xml_preparedocument @idoc OUTPUT, @vcXML -- SAVE THE XML in the @vcXML parameter into an -- internal table using OPENXML rowset provider INSERT INTO @myTable SELECT * FROM OPENXML (@idoc, '/ROOT/tblWorkloadCCRClinicToLabDetail',2) WITH ( uiWorkloadCCRFK uniqueidentifier '@uiWorkloadCCRFK' ,uiSiteClinicFK uniqueidentifier '@uiSiteClinicFK' ,uiSiteLabFK uniqueidentifier '@uiSiteLabFK' ,iLabSequence int '@iLabSequence' ,bIsRefundableLab bit '@bIsRefundableLab' ) -- Remove the internal representation of the XML -- document to clean up memory EXEC sp_xml_removedocument @idoc -- DELETE the rows in the table that match the -- uiWorkloadCCRFK in the XML parameter DELETE tblWorkloadCCRClinicToLabDetail WHERE uiWorkloadCCRFK IN (SELECT DISTINCT uiWorkloadCCRFK From @myTable) -- DELETE the rows in the table from the XML parameter INSERT INTO tblWorkloadCCRClinicToLabDetail SELECT * From @myTable COMMIT TRANSACTION END
-- ============================================= -- Author: Gary Janecek -- Create date: 3/29/2010 -- Description: Returns a temporary TABLE as a VARIABLE that converts a varchar(max) delimited list of UNIQUEIDENTIFIERS -- to a table with one field name (value) consisting of one row for each UNIQUEIDENTIFIER in the -- delimited list (@list) -- Where: @list is: -- A delimited string of GUIDS (i.e. '71805F81-FE46-4937-8FB5-0000236DDF5E,493E5B30-FBA6-442A-9E60-0000295FB4EE,6BE6A4C9-1693-4B3A-8DE2-00002C3BF337' -- @delimiter is -- A single CHAR that is the DELIMITER used to separate the values in the -- @list parameter. For example a comma (','). -- RETURNS: A temporary table VARIABLE with a single field (value) consisting of one row for each UNIQUEIDENTIFIER in the -- delimited list (@list) -- ============================================= CREATE FUNCTION [dbo].[ufn_DelimitedStringOfGUIDsToTable] ( @list varchar(max) ,@delimiter char(1) ) RETURNS @tableList TABLE (value uniqueidentifier) AS BEGIN DECLARE @value varchar(100) DECLARE @position int SET @list = LTRIM(RTRIM(@list)) + ',' SET @position = CHARINDEX(@delimiter, @list, 1) IF REPLACE (@list, @delimiter, '') <> '' BEGIN WHILE @position > 0 BEGIN SET @value = LTRIM(RTRIM(LEFT(@list, @position - 1))) IF @value <> '' BEGIN INSERT INTO @tableList (value) VALUES (@value) END SET @list = RIGHT(@list, LEN(@list) - @position) SET @position = CHARINDEX(@delimiter, @list, 1) END END RETURN END
-- ============================================= -- Author: Gary Janecek -- Create date: 3/29/2010 -- Description: Updates the bIsActive field of the tblXrefSpectacleService table -- by setting the field equal to its OPPOSITE value. -- Usage: PASS to this procedure ONE STRING which is a list of comma delimited GUIDS -- whose bIsActive (bit) field needs to be set based upon the @action parameter. -- If @Action parameter is -1, then you the bIsActive field will be FLIPPED to its OPPOSITE VALUE! -- If, for instance, you keep track of "modified" records, not those that are set to TRUE or FALSE, -- then you can call this procedure to flip the bit on the modified records, instead of calling a -- procedure to set n GUIDS to TRUE, and again to set n GUIDS to FALSE. This way, you can call -- ONE procedure to FLIP the values from what they are to its OPPOSITE. -- Where: @DelimitedStringOfUniqueIdentifierKeys is: -- A delimited string of GUIDS (i.e. '71805F81-FE46-4937-8FB5-0000236DDF5E,493E5B30-FBA6-442A-9E60-0000295FB4EE,6BE6A4C9-1693-4B3A-8DE2-00002C3BF337' -- @Delimiter is -- A single CHAR that is the DELIMITER used to separate the values in the -- @DelimitedStringOfUniqueIdentifierKeys parameter. For example a comma (','). -- @Action is -- -1 FLIP - FLIP the bIsActive field to its OPPOSITE VALUE -- 1 TRUE - Set the bIsActive field to 1 -- 0 FALSE - Set the bIsActive field to 0 -- ============================================= ALTER PROCEDURE UpdateXrefSpectacleServicebIsActive @DelimitedStringOfUniqueIdentifierKeys varchar(max) ,@Delimiter CHAR(1) ,@Action int AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Declare a temp variable as a TABLE type DECLARE @TempXRefSpectacleServiceKeys TABLE (value uniqueidentifier) -- COPY the delimited values into the temp Table INSERT INTO @TempXRefSpectacleServiceKeys (value) SELECT value FROM ufn_DelimitedStringOfGUIDsToTable(@DelimitedStringOfUniqueIdentifierKeys, @Delimiter) -- Now, Update tblXRefSpectacleService table based on the @action parameter IF @action = -1 -- FLIP the bit field value of the bIsActive field UPDATE tblXRefSpectacleService SET bIsActive = bIsActive ^ 1 WHERE uiXRefSpectacleServicePK in (select * from @TempXRefSpectacleServiceKeys) ELSE -- SET the bit field value of the bIsActive field to the @action parameter value UPDATE tblXRefSpectacleService SET bIsActive = @action WHERE uiXRefSpectacleServicePK in (select * from @TempXRefSpectacleServiceKeys) END GO
EXEC UpdateXrefSpectacleServicebIsActive '71805F81-FE46-4937-8FB5-0000236DDF5E,493E5B30-FBA6-442A-9E60-0000295FB4EE,6BE6A4C9-1693-4B3A-8DE2-00002C3BF337', ',', 1
INSERT [Specifications].[dbo].[tblSite] SELECT 1 as SiteTypeFK ,[c_labaccountcode] as ShortDescription ,[c_labaccountdescription] as LongDescription FROM [SRTS_Steve].[dbo].[tblLabAccount] INSERT [Specifications].[dbo].[tblSite] SELECT 2 as SiteTypeFK ,[c_clinicaccountcode] as ShortDescription ,[c_clidescription] as LongDescription FROM [SRTS_Steve].[dbo].[tblClinicAccount]
After deciding that you need an Xref table to create Many-to-Many relationships between data tables, you may find it difficult to pre-populate that xref table with some sample data for testing. I first thought of using some nested foreach() constructs to insert a unique row into the Xref table for each of the specific FK (Foreign Key) columns. Then, on the innermost foreach(), I would insert the unique row. This takes time to develop of course, but what's worse is that it takes a HORRIBLE amout of time to execute. I was following this procedure to insert 1.6 million rows in a Xref table that had 5 FK's - after 14 hours I had added 333K rows. At that rate I would have all of the rows in the Xref table only after about 80 hours of continuous database inserts.
Deciding that there must be a more efficient way, I began trying a SELECT FROM tb1, tb2, tb3, tb4, tb5 (listing all of the tables without JOINing any of them). Then, creating a NEW uniqueidentifier as the XrefPK, selecting only the FKs, naming the fields using the exact same names as the XRef table, then WRAP the SELECT statement with an INSERT XrefTable. See below. Executing this statement did EXACTLY the same thing I was doing in the first paragraph - BUT ONLY TOOK LESS THAN TWO MINUTES TO COMPLETE!
INSERT tblXrefSpectacleService Select NEWID() as uiXrefSpectacleServicePK, spec.uiSpectaclesPK as uiSpectaclesFK, ars.uiAntiReflectiveServicePK as uiAntiReflectiveServiceFK, t.uiTintPK as uiTintFK, uv.uiUVCoatingPK as uiUVCoatingFK, sr.uiScratchResistPK as uiScratchResistFK, 1.01 as mTotalSpectacleCost, 0 as bIsActive FROM tblSpectacles spec, tblAntiReflectiveService ars, tblTint t, tblUVCoating uv, tblScratchResist sr
/* ============================================= Author: Gary Janecek Create date: 4/20/2010 Description: Returns the Julian Date (YYDDD) as a char(5) Where: @date is: The datetime to be converted to Julian RETURNS: The Julian Date as a char(5) EXAMPLE: DECLARE @myDate datetime = '2010-03-15' Print dbo.ufn_ToJulianDate(@myDate) Print dbo.ufn_ToJulianDate(GetDate()) ============================================= */ CREATE FUNCTION [dbo].[ufn_ToJulianDate] ( @date datetime ) RETURNS char(5) AS BEGIN RETURN (SELECT RIGHT(CAST(YEAR(@date) AS CHAR(4)),2) + RIGHT('000' + CAST(DATEPART(dy, @date) AS varchar(3)),3)) END
/* ============================================= Author: Gary Janecek Create date: 4/20/2010 Description: Returns a Standard date from a Julian Date (YYDDD) Where: @JulianDate is: The JulianDate to be converted to Standard Date RETURNS: The StandardDate as a datetime EXAMPLE: DECLARE @myJulianDate char(5) = '10110' Print dbo.ufn_FromJulianDate(@myJulianDate) ============================================= */ ALTER FUNCTION [dbo].[ufn_FromJulianDate] ( @JulianDate char(5) ) RETURNS datetime AS BEGIN RETURN (SELECT DATEADD(day, CAST(RIGHT(@JulianDate,3) AS int) -1, CONVERT(datetime, LEFT(@JulianDate,2) + '0101',112))) END
SELECT convert(varchar, getdate(), 100) -- mon dd yyyy hh:mmAM (or PM) -- Oct 2 2010 11:01AM SELECT convert(varchar, getdate(), 101) -- mm/dd/yyyy - 10/02/2010 SELECT convert(varchar, getdate(), 102) -- yyyy.mm.dd - 2010.10.02 SELECT convert(varchar, getdate(), 103) -- dd/mm/yyyy SELECT convert(varchar, getdate(), 104) -- dd.mm.yyyy SELECT convert(varchar, getdate(), 105) -- dd-mm-yyyy SELECT convert(varchar, getdate(), 106) -- dd mon yyyy SELECT convert(varchar, getdate(), 107) -- mon dd, yyyy SELECT convert(varchar, getdate(), 108) -- hh:mm:ss SELECT convert(varchar, getdate(), 109) -- mon dd yyyy hh:mm:ss:mmmAM (or PM) -- Oct 2 2010 11:02:44:013AM SELECT convert(varchar, getdate(), 110) -- mm-dd-yyyy SELECT convert(varchar, getdate(), 111) -- yyyy/mm/dd SELECT convert(varchar, getdate(), 112) -- yyyymmdd SELECT convert(varchar, getdate(), 113) -- dd mon yyyy hh:mm:ss:mmm -- 02 Oct 2010 11:02:07:577 SELECT convert(varchar, getdate(), 114) -- hh:mm:ss:mmm(24h) SELECT convert(varchar, getdate(), 120) -- yyyy-mm-dd hh:mm:ss(24h) SELECT convert(varchar, getdate(), 121) -- yyyy-mm-dd hh:mm:ss.mmm SELECT convert(varchar, getdate(), 126) -- yyyy-mm-ddThh:mm:ss.mmm -- 2010-10-02T10:52:47.513 -- Without century (YY) date / datetime conversion - there are exceptions! SELECT convert(varchar, getdate(), 0) -- mon dd yyyy hh:mmAM (or PM) SELECT convert(varchar, getdate(), 1) -- mm/dd/yy SELECT convert(varchar, getdate(), 2) -- yy.mm.dd SELECT convert(varchar, getdate(), 3) -- dd/mm/yy SELECT convert(varchar, getdate(), 4) -- dd.mm.yy SELECT convert(varchar, getdate(), 5) -- dd-mm-yy SELECT convert(varchar, getdate(), 6) -- dd mon yy SELECT convert(varchar, getdate(), 7) -- mon dd, yy SELECT convert(varchar, getdate(), 8) -- hh:mm:ss SELECT convert(varchar, getdate(), 9) -- mon dd yyyy hh:mm:ss:mmmAM (or PM) SELECT convert(varchar, getdate(), 10) -- mm-dd-yy SELECT convert(varchar, getdate(), 11) -- yy/mm/dd SELECT convert(varchar, getdate(), 12) -- yymmdd SELECT convert(varchar, getdate(), 13) -- dd mon yyyy hh:mm:ss:mmm SELECT convert(varchar, getdate(), 14) -- hh:mm:ss:mmm(24h) SELECT convert(varchar, getdate(), 20) -- yyyy-mm-dd hh:mm:ss(24h) SELECT convert(varchar, getdate(), 21) -- yyyy-mm-dd hh:mm:ss.mmm SELECT convert(varchar, getdate(), 22) -- mm/dd/yy hh:mm:ss AM (or PM) SELECT convert(varchar, getdate(), 23) -- yyyy-mm-dd SELECT convert(varchar, getdate(), 24) -- hh:mm:ss SELECT convert(varchar, getdate(), 25) -- yyyy-mm-dd hh:mm:ss.mmm -- SQL create different date styles with t-sql string functions SELECT replace(convert(varchar, getdate(), 111), '/', ' ') -- yyyy mm dd SELECT convert(varchar(7), getdate(), 126) -- yyyy-mm SELECT right(convert(varchar, getdate(), 106), 8) -- mon yyyy SELECT substring(convert(varchar, getdate(), 120),6, 11) -- mm-dd hh:mm
/***** SELECTED SQL DATE/DATETIME FORMATS WITH NAMES *****/ -- SQL format datetime - - sql hh mm ss - sql yyyy mm dd -- Default format: Oct 23 2006 10:40AM SELECT [Default]=CONVERT(varchar,GETDATE(),100) -- US-Style format: 10/23/2006 SELECT [US-Style]=CONVERT(char,GETDATE(),101) -- ANSI format: 2006.10.23 SELECT [ANSI]=CONVERT(char,CURRENT_TIMESTAMP,102) -- UK-Style format: 23/10/2006 SELECT [UK-Style]=CONVERT(char,GETDATE(),103) -- German format: 23.10.2006 SELECT [German]=CONVERT(varchar,GETDATE(),104) -- ISO format: 20061023 SELECT ISO=CONVERT(varchar,GETDATE(),112) -- ISO8601 format: 2010-10-23T19:20:16.003 SELECT [ISO8601]=CONVERT(varchar,GETDATE(),126)
-- SQL Server datetime formats - Format dates SQL Server 2005 / 2008 -- Century date format MM/DD/YYYY usage in a query SELECT TOP (1) SalesOrderID, OrderDate = CONVERT(char(10), OrderDate, 101), OrderDateTime = OrderDate FROM AdventureWorks.Sales.SalesOrderHeader /* SalesOrderID OrderDate OrderDateTime 43697 07/01/2001 2001-07-01 00:00:00.000 */
------------ -- SQL Server date formatting function - convert datetime to string ------------ -- SQL datetime functions - SQL date functions - SQL datetime formatting -- SQL Server date formats - sql server date datetime - sql date formatting -- T-SQL convert dates - T-SQL date formats - Transact-SQL date formats -- Formatting dates sql server - sql convert datetime format CREATE FUNCTION dbo.fnFormatDate (@Datetime DATETIME, @FormatMask VARCHAR(32)) RETURNS VARCHAR(32) AS BEGIN DECLARE @StringDate VARCHAR(32) SET @StringDate = @FormatMask IF (CHARINDEX ('YYYY',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'YYYY', DATENAME(YY, @Datetime)) IF (CHARINDEX ('YY',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'YY', RIGHT(DATENAME(YY, @Datetime),2)) IF (CHARINDEX ('Month',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'Month', DATENAME(MM, @Datetime)) IF (CHARINDEX ('MON',@StringDate COLLATE SQL_Latin1_General_CP1_CS_AS)>0) SET @StringDate = REPLACE(@StringDate, 'MON', LEFT(UPPER(DATENAME(MM, @Datetime)),3)) IF (CHARINDEX ('Mon',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'Mon', LEFT(DATENAME(MM, @Datetime),3)) IF (CHARINDEX ('MM',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'MM', RIGHT('0'+CONVERT(VARCHAR,DATEPART(MM, @Datetime)),2)) IF (CHARINDEX ('M',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'M', CONVERT(VARCHAR,DATEPART(MM, @Datetime))) IF (CHARINDEX ('DD',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'DD', RIGHT('0'+DATENAME(DD, @Datetime),2)) IF (CHARINDEX ('D',@StringDate) > 0) SET @StringDate = REPLACE(@StringDate, 'D', DATENAME(DD, @Datetime)) RETURN @StringDate END GO -- Microsoft SQL Server date format function test -- MSSQL formatting dates - sql datetime date SELECT dbo.fnFormatDate (getdate(), 'MM/DD/YYYY') -- 01/03/2012 SELECT dbo.fnFormatDate (getdate(), 'DD/MM/YYYY') -- 03/01/2012 SELECT dbo.fnFormatDate (getdate(), 'M/DD/YYYY') -- 1/03/2012 SELECT dbo.fnFormatDate (getdate(), 'M/D/YYYY') -- 1/3/2012 SELECT dbo.fnFormatDate (getdate(), 'M/D/YY') -- 1/3/12 SELECT dbo.fnFormatDate (getdate(), 'MM/DD/YY') -- 01/03/12 SELECT dbo.fnFormatDate (getdate(), 'MON DD, YYYY') -- JAN 03, 2012 SELECT dbo.fnFormatDate (getdate(), 'Mon DD, YYYY') -- Jan 03, 2012 SELECT dbo.fnFormatDate (getdate(), 'Month DD, YYYY') -- January 03, 2012 SELECT dbo.fnFormatDate (getdate(), 'YYYY/MM/DD') -- 2012/01/03 SELECT dbo.fnFormatDate (getdate(), 'YYYYMMDD') -- 20120103 SELECT dbo.fnFormatDate (getdate(), 'YYYY-MM-DD') -- 2012-01-03 -- CURRENT_TIMESTAMP returns current system date and time in standard internal format SELECT dbo.fnFormatDate (CURRENT_TIMESTAMP,'YY.MM.DD') -- 12.01.03 GO
-- SQL update datetime column - SQL datetime DATEADD - datetime function UPDATE Production.Product SET ModifiedDate=DATEADD(dd,1, ModifiedDate) WHERE ProductID = 1001 -- MM/DD/YY date format - Datetime format sql SELECT TOP (1) SalesOrderID, OrderDate = CONVERT(varchar(8), OrderDate, 1), OrderDateTime = OrderDate FROM AdventureWorks.Sales.SalesOrderHeader ORDER BY SalesOrderID desc /* SalesOrderID OrderDate OrderDateTime 75123 07/31/04 2004-07-31 00:00:00.000 */
-- SQL convert datetime to char - sql date string concatenation: + (plus) operator PRINT 'Style 110: '+CONVERT(CHAR(10),GETDATE(),110) -- Style 110: 07-10-2012 PRINT 'Style 111: '+CONVERT(CHAR(10),GETDATE(),111) -- Style 111: 2012/07/10 PRINT 'Style 112: '+CONVERT(CHAR(8), GETDATE(),112) -- Style 112: 20120710
-- Combining different style formats for date & time -- Datetime formats - sql times format - datetime formats sql DECLARE @Date DATETIME SET @Date = '2015-12-22 03:51 PM' SELECT CONVERT(CHAR(10),@Date,110) + SUBSTRING(CONVERT(varchar,@Date,0),12,8) -- Result: 12-22-2015 3:51PM -- Microsoft SQL Server cast datetime to string SELECT stringDateTime=CAST (getdate() as varchar) -- Result: Dec 29 2012 3:47AM
-- SQL Server CURRENT_TIMESTAMP function -- SQL Server datetime functions -- local NYC - EST - Eastern Standard Time zone -- SQL DATEADD function - SQL DATEDIFF function SELECT CURRENT_TIMESTAMP -- 2012-01-05 07:02:10.577 -- SQL Server DATEADD function SELECT DATEADD(month,2,'2012-12-09') -- 2013-02-09 00:00:00.000 -- SQL Server DATEDIFF function SELECT DATEDIFF(day,'2012-12-09','2013-02-09') -- 62 -- SQL Server DATENAME function SELECT DATENAME(month, '2012-12-09') -- December SELECT DATENAME(weekday, '2012-12-09') -- Sunday -- SQL Server DATEPART function SELECT DATEPART(month, '2012-12-09') -- 12 -- SQL Server DAY function SELECT DAY('2012-12-09') -- 9 -- SQL Server GETDATE function -- local NYC - EST - Eastern Standard Time zone SELECT GETDATE() -- 2012-01-05 07:02:10.577 -- SQL Server GETUTCDATE function -- London - Greenwich Mean Time SELECT GETUTCDATE() -- 2012-01-05 12:02:10.577 -- SQL Server MONTH function SELECT MONTH('2012-12-09') -- 12 -- SQL Server YEAR function SELECT YEAR('2012-12-09') -- 2012
-- T-SQL first day of week and last day of week SELECT FirstDateOfWeek = dateadd(dd,-DATEPART(dw,GETDATE()) + 1,GETDATE()) SELECT LastDateOfWeek = dateadd(dd,7 - DATEPART(dw,GETDATE()),GETDATE()) -- SQL first day of the month -- SQL first date of the month -- SQL first day of current month - 2012-01-01 00:00:00.000 SELECT DATEADD(dd,0,DATEADD(mm, DATEDIFF(mm,0,CURRENT_TIMESTAMP),0)) -- SQL last day of the month -- SQL last date of the month -- SQL last day of current month - 2012-01-31 00:00:00.000 SELECT DATEADD(dd,-1,DATEADD(mm, DATEDIFF(mm,0,CURRENT_TIMESTAMP)+1,0)) -- SQL first day of last month -- SQL first day of previous month - 2011-12-01 00:00:00.000 SELECT DATEADD(mm,-1,DATEADD(mm, DATEDIFF(mm,0,CURRENT_TIMESTAMP),0)) -- SQL last day of last month -- SQL last day of previous month - 2011-12-31 00:00:00.000 SELECT DATEADD(dd,-1,DATEADD(mm, DATEDIFF(mm,0,DATEADD(MM,-1,GETDATE()))+1,0)) -- SQL first day of next month - 2012-02-01 00:00:00.000 SELECT DATEADD(mm,1,DATEADD(mm, DATEDIFF(mm,0,CURRENT_TIMESTAMP),0)) -- SQL last day of next month - 2012-02-28 00:00:00.000 SELECT DATEADD(dd,-1,DATEADD(mm, DATEDIFF(mm,0,DATEADD(MM,1,GETDATE()))+1,0)) GO -- SQL first day of a month - 2012-10-01 00:00:00.000 DECLARE @Date datetime; SET @Date = '2012-10-23' SELECT DATEADD(dd,0,DATEADD(mm, DATEDIFF(mm,0,@Date),0)) GO -- SQL last day of a month - 2012-03-31 00:00:00.000 DECLARE @Date datetime; SET @Date = '2012-03-15' SELECT DATEADD(dd,-1,DATEADD(mm, DATEDIFF(mm,0,@Date)+1,0)) GO -- SQL first day of year -- SQL first day of the year - 2012-01-01 00:00:00.000 SELECT DATEADD(yy, DATEDIFF(yy,0,CURRENT_TIMESTAMP), 0) -- SQL last day of year -- SQL last day of the year - 2012-12-31 00:00:00.000 SELECT DATEADD(yy,1, DATEADD(dd, -1, DATEADD(yy, DATEDIFF(yy,0,CURRENT_TIMESTAMP), 0))) -- SQL last day of last year -- SQL last day of previous year - 2011-12-31 00:00:00.000 SELECT DATEADD(dd,-1,DATEADD(yy,DATEDIFF(yy,0,CURRENT_TIMESTAMP), 0)) GO -- SQL calculate age in years, months, days - Format dates SQL Server 2008 -- SQL table-valued function - SQL user-defined function - UDF -- SQL Server age calculation - date difference USE AdventureWorks2008; GO CREATE FUNCTION fnAge (@BirthDate DATETIME) RETURNS @Age TABLE(Years INT, Months INT, Days INT) AS BEGIN DECLARE @EndDate DATETIME, @Anniversary DATETIME SET @EndDate = Getdate() SET @Anniversary = Dateadd(yy,Datediff(yy,@BirthDate,@EndDate),@BirthDate) INSERT @Age SELECT Datediff(yy,@BirthDate,@EndDate) - (CASE WHEN @Anniversary > @EndDate THEN 1 ELSE 0 END), 0, 0 UPDATE @Age SET Months = Month(@EndDate - @Anniversary) - 1 UPDATE @Age SET Days = Day(@EndDate - @Anniversary) - 1 RETURN END GO -- Test table-valued UDF SELECT * FROM fnAge('1956-10-23') SELECT * FROM dbo.fnAge('1956-10-23') /* Results Years Months Days 52 4 1 */
-- SQL between dates USE AdventureWorks; -- SQL between SELECT POs=COUNT(*) FROM Purchasing.PurchaseOrderHeader WHERE OrderDate BETWEEN '20040301' AND '20040315' -- Result: 108 -- BETWEEN operator is equivalent to >=...AND....<= SELECT POs=COUNT(*) FROM Purchasing.PurchaseOrderHeader WHERE OrderDate BETWEEN '2004-03-01 00:00:00.000' AND '2004-03-15 00:00:00.000' /* Orders with OrderDates '2004-03-15 00:00:01.000' - 1 second after midnight (12:00AM) '2004-03-15 00:01:00.000' - 1 minute after midnight '2004-03-15 01:00:00.000' - 1 hour after midnight are not included in the two queries above. */ -- To include the entire day of 2004-03-15 use the following two solutions SELECT POs=COUNT(*) FROM Purchasing.PurchaseOrderHeader WHERE OrderDate >= '20040301' AND OrderDate < '20040316' -- SQL between with DATE type (SQL Server 2008) SELECT POs=COUNT(*) FROM Purchasing.PurchaseOrderHeader WHERE CONVERT(DATE, OrderDate) BETWEEN '20040301' AND '20040315'
-- Non-standard format conversion: 2011 December 14 -- SQL datetime to string SELECT [YYYY Month DD] = CAST(YEAR(GETDATE()) AS VARCHAR(4))+ ' '+ DATENAME(MM, GETDATE()) + ' ' + CAST(DAY(GETDATE()) AS VARCHAR(2)) -- Converting datetime to YYYYMMDDHHMMSS format: 20121214172638 SELECT replace(convert(varchar, getdate(),111),'/','') + replace(convert(varchar, getdate(),108),':','') -- Datetime custom format conversion to YYYY_MM_DD select CurrentDate=rtrim(year(getdate())) + '_' + right('0' + rtrim(month(getdate())),2) + '_' + right('0' + rtrim(day(getdate())),2) -- Converting seconds to HH:MM:SS format declare @Seconds int set @Seconds = 10000 select TimeSpan=right('0' +rtrim(@Seconds / 3600),2) + ':' + right('0' + rtrim((@Seconds % 3600) / 60),2) + ':' + right('0' + rtrim(@Seconds % 60),2) -- Result: 02:46:40 -- Test result select 2*3600 + 46*60 + 40 -- Result: 10000 -- Set the time portion of a datetime value to 00:00:00.000 -- SQL strip time from date -- SQL strip time from datetime SELECT CURRENT_TIMESTAMP ,DATEADD(dd, DATEDIFF(dd, 0, CURRENT_TIMESTAMP), 0) -- Results: 2014-01-23 05:35:52.793 2014-01-23 00:00:00.000
/* VALID DATE RANGES FOR DATE/DATETIME DATA TYPES
SMALLDATETIME (4 bytes) date range:
January 1, 1900 through June 6, 2079
DATETIME (8 bytes) date range:
January 1, 1753 through December 31, 9999
DATETIME2 (8 bytes) date range (SQL Server 2008):
January 1,1 AD through December 31, 9999 AD
DATE (3 bytes) date range (SQL Server 2008):
January 1, 1 AD through December 31, 9999 AD
-- Selecting with CONVERT into different styles -- Note: Only Japan & ISO styles can be used in ORDER BY SELECT TOP(1) Italy = CONVERT(varchar, OrderDate, 105) , USA = CONVERT(varchar, OrderDate, 110) , Japan = CONVERT(varchar, OrderDate, 111) , ISO = CONVERT(varchar, OrderDate, 112) FROM AdventureWorks.Purchasing.PurchaseOrderHeader ORDER BY PurchaseOrderID DESC /* Results Italy USA Japan ISO 25-07-2004 07-25-2004 2004/07/25 20040725 */ -- SQL Server convert date to integer DECLARE @Datetime datetime SET @Datetime = '2012-10-23 10:21:05.345' SELECT DateAsInteger = CAST (CONVERT(varchar,@Datetime,112) as INT) -- Result: 20121023 -- SQL Server convert integer to datetime DECLARE @intDate int SET @intDate = 20120315 SELECT IntegerToDatetime = CAST(CAST(@intDate as varchar) as datetime) -- Result: 2012-03-15 00:00:00.000
-- SQL Server CONVERT script applying table INSERT/UPDATE ------------ -- SQL Server convert date -- Datetime column is converted into date only string column USE tempdb; GO CREATE TABLE sqlConvertDateTime ( DatetimeCol datetime, DateCol char(8)); INSERT sqlConvertDateTime (DatetimeCol) SELECT GETDATE() UPDATE sqlConvertDateTime SET DateCol = CONVERT(char(10), DatetimeCol, 112) SELECT * FROM sqlConvertDateTime -- SQL Server convert datetime -- The string date column is converted into datetime column UPDATE sqlConvertDateTime SET DatetimeCol = CONVERT(Datetime, DateCol, 112) SELECT * FROM sqlConvertDateTime -- Adding a day to the converted datetime column with DATEADD UPDATE sqlConvertDateTime SET DatetimeCol = DATEADD(day, 1, CONVERT(Datetime, DateCol, 112)) SELECT * FROM sqlConvertDateTime -- Equivalent formulation -- SQL Server cast datetime UPDATE sqlConvertDateTime SET DatetimeCol = DATEADD(dd, 1, CAST(DateCol AS datetime)) SELECT * FROM sqlConvertDateTime GO DROP TABLE sqlConvertDateTime GO /* First results DatetimeCol DateCol 2014-12-25 16:04:15.373 20141225 */ /* Second results: DatetimeCol DateCol 2014-12-25 00:00:00.000 20141225 */ /* Third results: DatetimeCol DateCol 2014-12-26 00:00:00.000 20141225 */
-- SQL month sequence - SQL date sequence generation with table variable -- SQL Server cast string to datetime - SQL Server cast datetime to string -- SQL Server insert default values method ------------ DECLARE @Sequence table (Sequence int identity(1,1)) DECLARE @i int; SET @i = 0 DECLARE @StartDate datetime; SET @StartDate = CAST(CONVERT(varchar, year(getdate()))+ RIGHT('0'+convert(varchar,month(getdate())),2) + '01' AS DATETIME) WHILE ( @i < 120) BEGIN INSERT @Sequence DEFAULT VALUES SET @i = @i + 1 END SELECT MonthSequence = CAST(DATEADD(month, Sequence,@StartDate) AS varchar) FROM @Sequence GO /* Partial results: MonthSequence Jan 1 2012 12:00AM Feb 1 2012 12:00AM Mar 1 2012 12:00AM Apr 1 2012 12:00AM */
-- SQL Server Server datetime internal storage -- SQL Server datetime formats ------------ -- SQL Server datetime to hex SELECT Now=CURRENT_TIMESTAMP, HexNow=CAST(CURRENT_TIMESTAMP AS BINARY(8)) /* Results Now HexNow 2009-01-02 17:35:59.297 0x00009B850122092D */ -- SQL Server date part - left 4 bytes - Days since 1900-01-01 SELECT Now=DATEADD(DAY, CONVERT(INT, 0x00009B85), '19000101') GO -- Result: 2009-01-02 00:00:00.000 -- SQL time part - right 4 bytes - milliseconds since midnight -- 1000/300 is an adjustment factor -- SQL dateadd to Midnight SELECT Now=DATEADD(MS, (1000.0/300)* CONVERT(BIGINT, 0x0122092D), '2009-01-02') GO -- Result: 2009-01-02 17:35:59.290
-- String date and datetime date&time columns usage -- SQL Server datetime formats in tables ------------ USE tempdb; SET NOCOUNT ON; -- SQL Server select into table create SELECT TOP (5) FullName=convert(nvarchar(50),FirstName+' '+LastName), BirthDate = CONVERT(char(8), BirthDate,112), ModifiedDate = getdate() INTO Employee FROM AdventureWorks.HumanResources.Employee e INNER JOIN AdventureWorks.Person.Contact c ON c.ContactID = e.ContactID ORDER BY EmployeeID GO -- SQL Server alter table ALTER TABLE Employee ALTER COLUMN FullName nvarchar(50) NOT NULL GO ALTER TABLE Employee ADD CONSTRAINT [PK_Employee] PRIMARY KEY (FullName ) GO /* Results Table definition for the Employee table Note: BirthDate is string date (only) CREATE TABLE dbo.Employee( FullName nvarchar(50) NOT NULL PRIMARY KEY, BirthDate char(8) NULL, ModifiedDate datetime NOT NULL ) */ SELECT * FROM Employee ORDER BY FullName GO /* Results FullName BirthDate ModifiedDate Guy Gilbert 19720515 2009-01-03 10:10:19.217 Kevin Brown 19770603 2009-01-03 10:10:19.217 Rob Walters 19650123 2009-01-03 10:10:19.217 Roberto Tamburello 19641213 2009-01-03 10:10:19.217 Thierry D'Hers 19490829 2009-01-03 10:10:19.217 */ -- SQL Server age SELECT FullName, Age = DATEDIFF(YEAR, BirthDate, GETDATE()), RowMaintenanceDate = CAST (ModifiedDate AS varchar) FROM Employee ORDER BY FullName GO /* Results FullName Age RowMaintenanceDate Guy Gilbert 37 Jan 3 2009 10:10AM Kevin Brown 32 Jan 3 2009 10:10AM Rob Walters 44 Jan 3 2009 10:10AM Roberto Tamburello 45 Jan 3 2009 10:10AM Thierry D'Hers 60 Jan 3 2009 10:10AM */ -- SQL Server age of Rob Walters on specific dates -- SQL Server string to datetime implicit conversion with DATEADD SELECT AGE50DATE = DATEADD(YY, 50, '19650123') GO -- Result: 2015-01-23 00:00:00.000 -- SQL Server datetime to string, Italian format for ModifiedDate -- SQL Server string to datetime implicit conversion with DATEDIFF SELECT FullName, AgeDEC31 = DATEDIFF(YEAR, BirthDate, '20141231'), AgeJAN01 = DATEDIFF(YEAR, BirthDate, '20150101'), AgeJAN23 = DATEDIFF(YEAR, BirthDate, '20150123'), AgeJAN24 = DATEDIFF(YEAR, BirthDate, '20150124'), ModDate = CONVERT(varchar, ModifiedDate, 105) FROM Employee WHERE FullName = 'Rob Walters' ORDER BY FullName GO /* Results Important Note: age increments on Jan 1 (not as commonly calculated) FullName AgeDEC31 AgeJAN01 AgeJAN23 AgeJAN24 ModDate Rob Walters 49 50 50 50 03-01-2009 */
------------ -- SQL combine integer date & time into datetime ------------ -- Datetime format sql -- SQL stuff DECLARE @DateTimeAsINT TABLE ( ID int identity(1,1) primary key, DateAsINT int, TimeAsINT int ) -- NOTE: leading zeroes in time is for readability only! INSERT @DateTimeAsINT (DateAsINT, TimeAsINT) VALUES (20121023, 235959) INSERT @DateTimeAsINT (DateAsINT, TimeAsINT) VALUES (20121023, 010204) INSERT @DateTimeAsINT (DateAsINT, TimeAsINT) VALUES (20121023, 002350) INSERT @DateTimeAsINT (DateAsINT, TimeAsINT) VALUES (20121023, 000244) INSERT @DateTimeAsINT (DateAsINT, TimeAsINT) VALUES (20121023, 000050) INSERT @DateTimeAsINT (DateAsINT, TimeAsINT) VALUES (20121023, 000006) SELECT DateAsINT, TimeAsINT, CONVERT(datetime, CONVERT(varchar(8), DateAsINT) + ' '+ STUFF(STUFF ( RIGHT(REPLICATE('0', 6) + CONVERT(varchar(6), TimeAsINT), 6), 3, 0, ':'), 6, 0, ':')) AS DateTimeValue FROM @DateTimeAsINT ORDER BY ID GO /* Results DateAsINT TimeAsINT DateTimeValue 20121023 235959 2012-10-23 23:59:59.000 20121023 10204 2012-10-23 01:02:04.000 20121023 2350 2012-10-23 00:23:50.000 20121023 244 2012-10-23 00:02:44.000 20121023 50 2012-10-23 00:00:50.000 20121023 6 2012-10-23 00:00:06.000 */
-- SQL Server string to datetime, implicit conversion with assignment UPDATE Employee SET ModifiedDate = '20150123' WHERE FullName = 'Rob Walters' GO SELECT ModifiedDate FROM Employee WHERE FullName = 'Rob Walters' GO -- Result: 2015-01-23 00:00:00.000 /* SQL string date, assemble string date from datetime parts */ -- SQL Server cast string to datetime - sql convert string date -- SQL Server number to varchar conversion -- SQL Server leading zeroes for month and day -- SQL Server right string function UPDATE Employee SET BirthDate = CONVERT(char(4),YEAR(CAST('1965-01-23' as DATETIME)))+ RIGHT('0'+CONVERT(varchar,MONTH(CAST('1965-01-23' as DATETIME))),2)+ RIGHT('0'+CONVERT(varchar,DAY(CAST('1965-01-23' as DATETIME))),2) WHERE FullName = 'Rob Walters' GO SELECT BirthDate FROM Employee WHERE FullName = 'Rob Walters' GO -- Result: 19650123 -- Perform cleanup action DROP TABLE Employee -- SQL nocount SET NOCOUNT OFF; GO ------------ ------------ -- sql isdate function ------------ USE tempdb; -- sql newid - random sort SELECT top(3) SalesOrderID, stringOrderDate = CAST (OrderDate AS varchar) INTO DateValidation FROM AdventureWorks.Sales.SalesOrderHeader ORDER BY NEWID() GO SELECT * FROM DateValidation /* Results SalesOrderID stringOrderDate 56720 Oct 26 2003 12:00AM 73737 Jun 25 2004 12:00AM 70573 May 14 2004 12:00AM */ -- SQL update with top UPDATE TOP(1) DateValidation SET stringOrderDate = 'Apb 29 2004 12:00AM' GO -- SQL string to datetime fails without validation SELECT SalesOrderID, OrderDate = CAST (stringOrderDate as datetime) FROM DateValidation GO /* Msg 242, Level 16, State 3, Line 1 The conversion of a varchar data type to a datetime data type resulted in an out-of-range value. */ -- sql isdate - filter for valid dates SELECT SalesOrderID, OrderDate = CAST (stringOrderDate as datetime) FROM DateValidation WHERE ISDATE(stringOrderDate) = 1 GO /* Results SalesOrderID OrderDate 73737 2004-06-25 00:00:00.000 70573 2004-05-14 00:00:00.000 */ -- SQL drop table DROP TABLE DateValidation Go
------------ -- SELECT between two specified dates - assumption TIME part is 00:00:00.000 ------------ -- SQL datetime between -- SQL select between two dates SELECT EmployeeID, RateChangeDate FROM AdventureWorks.HumanResources.EmployeePayHistory WHERE RateChangeDate >= '1997-11-01' AND RateChangeDate < DATEADD(dd,1,'1998-01-05') GO /* Results EmployeeID RateChangeDate 3 1997-12-12 00:00:00.000 4 1998-01-05 00:00:00.000 */ /* Equivalent to -- SQL datetime range SELECT EmployeeID, RateChangeDate FROM AdventureWorks.HumanResources.EmployeePayHistory WHERE RateChangeDate >= '1997-11-01 00:00:00' AND RateChangeDate < '1998-01-06 00:00:00' GO */
-- SQL datetime language setting -- SQL Nondeterministic function usage - result varies with language settings SET LANGUAGE 'us_english'; –– Jan 12 2015 12:00AM SELECT US = convert(VARCHAR,convert(DATETIME,'01/12/2015')); SET LANGUAGE 'British'; –– Dec 1 2015 12:00AM SELECT UK = convert(VARCHAR,convert(DATETIME,'01/12/2015')); SET LANGUAGE 'German'; –– Dez 1 2015 12:00AM SET LANGUAGE 'Deutsch'; –– Dez 1 2015 12:00AM SELECT Germany = convert(VARCHAR,convert(DATETIME,'01/12/2015')); SET LANGUAGE 'French'; –– déc 1 2015 12:00AM SELECT France = convert(VARCHAR,convert(DATETIME,'01/12/2015')); SET LANGUAGE 'Spanish'; –– Dic 1 2015 12:00AM SELECT Spain = convert(VARCHAR,convert(DATETIME,'01/12/2015')); SET LANGUAGE 'Hungarian'; –– jan 12 2015 12:00AM SELECT Hungary = convert(VARCHAR,convert(DATETIME,'01/12/2015')); SET LANGUAGE 'us_english'; GO
------------ -- Function for Monday dates calculation ------------ USE AdventureWorks2008; GO -- SQL user-defined function -- SQL scalar function - UDF CREATE FUNCTION fnMondayDate (@Year INT, @Month INT, @MondayOrdinal INT) RETURNS DATETIME AS BEGIN DECLARE @FirstDayOfMonth CHAR(10), @SeedDate CHAR(10) SET @FirstDayOfMonth = convert(VARCHAR,@Year) + '-' + convert(VARCHAR,@Month) + '-01' SET @SeedDate = '1900-01-01' RETURN DATEADD(DD,DATEDIFF(DD,@SeedDate,DATEADD(DD,(@MondayOrdinal * 7) - 1, @FirstDayOfMonth)) / 7 * 7, @SeedDate) END GO -- Test Datetime UDF -- Third Monday in Feb, 2015 SELECT dbo.fnMondayDate(2016,2,3) -- 2015-02-16 00:00:00.000 -- First Monday of current month SELECT dbo.fnMondayDate(Year(getdate()),Month(getdate()),1) -- 2009-02-02 00:00:00.000
SQL Connection pooling is a problem, especially with older code, that Linq-to-SQL and .NET handles perfectly. Symptoms of poorly constructed code that cause connection pooling problems could show themselves by random connection timeouts to the SQL Server database. Constucting better code with Linq/.NET can solve many, if not all, of the connection pooling problems.
This section demonstrats a single method to monitor the SQL Server for Connection Pool issues. If, by using this method, you determine that you may have some Connection pooling issues, refer to the section for Connection Pool Refactoring.
Start Performance Monitor (perfmon) on the database server. Start -> Administrative Tools -> Performance Open the Properties dialog of the Counters. Remove all of the counters, add the counter below and click OK, OK. SQLServer: General Statistics, User Connections. Observe the number of user connections. Now, start the CMIS application and observe the number of user connections. The number of connections should only increase by 10 at most. If it climbs to more than 10 user connections, then note the module that is running. There is definitely an opportunity to re-factor the offending module.
When trying to find a unique set of fields upon which to set up an index for a table, you must find out which fields in an existing table create a unique row. Add as many dupeField(x) as necessary, then execute and check the row count.
-- Find out how many 'ROWSinTable' are in the table. SELECT Count(*) FROM EmployeeTable -- Update 'dupeFieldx' for fields that you feel would uniquely identify a row. -- Run the statement and look for the number of 'ROWSreturned' to match 'ROWSinTable'. -- When they match, then you have your fields that make a unique row in that table. SELECT * FROM EmployeeTable a WHERE 1 < ( SELECT COUNT(*) FROM EmployeeTable b WHERE a.dupeField1 = b.dupeField1 AND a.dupeField2 = b.dupeField2 AND a.dupeField3 = b.dupeField3 )
Becuase SQL Server ignores whitespace in the data, you may be getting different query results than you expect.
As a best practice, Empty Strings ('') and any fields that include whitespace should NOT be insterted into a table. This is
to avoid the IGNORE WHITESPACE problem with SQL Server. Instead, Best Practices dictate that EMPTY STRINGS should be replaced
with NULL when insterting into a table, and WHITESPACE should be removed from the data prior to insterting it into a table.
Note also that the WHITESPACE removal of data should be explicitly performed by the program insterting the data, and not left
up to SQL Server to implicitly pre-cate or truncate the whitespace from the beginning or end of the string data being inserted.
Also, the [seemingly] authentic use of any whitespace all by itself as data (for example, using a space {' '} as a valid code
amongst other single character codes such as 'B', 'W', and 'H' to indicate nothing was selected) is a very poor database design
practice. Instead, Best Practices would design a table much differently - but that's another article.
The code below demonstrates how an EMPTY STRING ('') and a SPACE (' ') can confuse and cause very wierd query results.
The conclusion of this discussion is only to say: AVOID designing a table that can produce these very wierd query results.
Recognize also, that by default, SQL treats an EMPTY STRING and a SPACE in exactly the same manner when they are placed in
a WHERE clause or an GROUP BY clause. The GROUP BY clause creates an additional oddity - it will report the GROUP using
the FIRST value found in the table. If a SPACE (' ') is in the first row, and EMPTY STRINGS are in all other rows, the query
results will report that there are only SPACEs (' ') in the table [since that was the first match found]. And, by reversing
the situation, if an EMPTY STRING ('') is in the first row, and SPACEs (' ') are in all other rows, the query results will
report that there are only EMPTY STRINGs ('') in the table [since that was the first match found]. --- VERY WIERD INDEED!
-- Create a table with a varchar(1) field CREATE TABLE [dbo].[temptest]( [Field1] [varchar](1) NULL ) ON [PRIMARY] -- Insert some values.. NOTE that an EMPTY STRING is in the FIRST ROW, -- and a SPACE CHAR (' ') is in the SECOND ROW. INSERT temptest (Field1) Values ('') INSERT temptest (Field1) Values (' ') -- Standard SELECT with no WHERE clause returns all rows in the table. Select '|' + Field1 + '|' as FieldOne From temptest -- FieldOne -- -------- -- || -- | | -- Executing a SELECT SEARCHING for the EMPTY STRING only in the FIRST ROW -- STILL returns all rows in the table. You would think that you should -- only get the match on the FIRST ROW. Select '|' + Field1 + '|' as FieldOne From temptest where Field1 = '' -- FieldOne -- -------- -- || -- | | -- Executing a SELECT SEARCHING for the SPACE CHAR (' ') only in the SECOND ROW -- STILL returns all rows in the table. You would think that you should -- only get the match on the SECOND ROW. Select '|' + Field1 + '|' as FieldOne From temptest where Field1 = ' ' -- FieldOne -- -------- -- || -- | | -- Executing a SELECT SEARCHING for the EMPTY STRING only in the FIRST ROW -- with a GROUP BY returns only one group of EMPTY STRING. You would think -- that you should get the a group for the EMPTY STRING [in the FIRST ROW] -- and another for the SPACE (' ') [in the SECOND ROW]. Select '|' + Field1 + '|' as FieldOne From temptest where Field1 = '' group by Field1 -- FieldOne -- -------- -- || -- Executing a SELECT WITHOUT ANY CONDITIONS -- with a GROUP BY returns only one group of EMPTY STRING. You would think -- that you should get the a group for the EMPTY STRING [in the FIRST ROW] -- and another for the SPACE (' ') [in the SECOND ROW]. Select '|' + Field1 + '|' as FieldOne From temptest group by Field1 -- FieldOne -- -------- -- || -- Now, Delete the data in the table and add new data. This time inserting -- the SPACE(' ') into the FIRST ROW and the EMPTY STRING into the SECOND ROW. -- This configuration will change the results of the same queries executed -- above. Delete Temptest INSERT temptest (Field1) Values (' ') INSERT temptest (Field1) Values ('') -- Standard SELECT with no WHERE clause returns all rows in the table Select '|' + Field1 + '|' as FieldOne From temptest -- FieldOne -- -------- -- | | -- || -- Executing a SELECT SEARCHING for the EMPTY STRING only in the SECOND ROW -- STILL returns all rows in the table. You would think that you should -- only get the match on the SECOND ROW. Select '|' + Field1 + '|' as FieldOne From temptest where Field1 = '' -- FieldOne -- -------- -- | | -- || -- Executing a SELECT SEARCHING for the SPACE CHAR (' ') only in the FIRST ROW -- STILL returns all rows in the table. You would think that you should -- only get the match on the FIRST ROW. Select '|' + Field1 + '|' as FieldOne From temptest where Field1 = ' ' -- FieldOne -- -------- -- | | -- || -- Here is where it gets interesting... -- Executing a SELECT SEARCHING for the EMPTY STRING only in the SECOND ROW -- with a GROUP BY returns only one group of SPACE (' '). You would think -- that you should get the a group for the SPACE (' ') [in the FIRST ROW] -- and another for the EMPTY STRING [in the SECOND ROW]. Select '|' + Field1 + '|' as FieldOne From temptest where field1 = '' group by Field1 -- FieldOne -- -------- -- | | -- Executing a SELECT WITHOUT ANY CONDITIONS -- with a GROUP BY returns only one group of SPACE (' '). You would think -- that you should get the a group for the SPACE (' ') [in the FIRST ROW] -- and another for the EMPTY STRING [in the SECOND ROW]. Select '|' + Field1 + '|' as FieldOne From temptest group by Field1 -- FieldOne -- -------- -- | |
/* Get all of the column information from the Schema */ SELECT * FROM INFORMATION_SCHEMA.COLUMNS /* Output TableName.ColumnName for each table and column, in sorted order */ SELECT TABLE_NAME + '.' + COLUMN_NAME as TableColumn FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, COLUMN_NAME /* Output TableName.ColumnName for each table and column, in the order that is already in each table (ORDINAL_POSITION) */ SELECT TABLE_NAME + '.' + COLUMN_NAME as TableColumn FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION
NOTE: It is really NOT the duty of the database to create PRESENTATION LAYER objects, such as Concatenating An Address. However, creating views that have a presentation object (like concatenating an address) can be useful if it is used in multiple places in the PRESENTATION LAYER, to enable code-reuse control of the presentation of data.
create table cm_customers_test (id int, address_1 varchar(30), address_2 varchar(30), address_3 varchar(30), address_4 varchar(30), city varchar(30), county varchar(30)) INSERT INTO CM_CUSTOMERS_TEST values (99999999,'4 O Donoghue Park','', '', '','Bessbrook','Down') --This is trying to make sure that values are not duplicated or any spaces are left between each field, --however its ok if there was a space if there was only 3 address full, to have a space after the SELECT id as CUSTOMERNUMBER ,CASE WHEN address_1 = '' then address_2 WHEN address_1 = ''and address_2 ='' then address_3 WHEN address_1 = '' and address_2 = '' and address_3 = '' then address_4 WHEN address_1 = '' and address_2 = '' and address_3 = '' and address_4 = '' then city WHEN address_1 = '' and address_2 = '' and address_3 = '' and address_4 = '' and city = '' then county Else Address_1 END ADDRESS_LINE_1 ,CASE WHEN address_2 = address_1 then address_3 else address_2 End ADDRESS_LINE_2 ,CASE WHEN address_3 = address_2 or address_3 = address_4 or address_4 = city then county WHEN address_3 = address_2 or address_3 = address_4 or address_4 = city or city = county then county Else address_3 End ADDRESS_LINE_3 ,CASE WHEN address_3 = address_4 or address_4 = city or city = county then '' WHEN address_3 = address_4 or address_4 = city then county Else Address_4 END ADDRESS_LINE_4 ,CASE WHEN address_4 = city or city = county then '' WHEN address_4 = city or city = county then county ELSE City END City ,CASE WHEN address_1 = county or address_2 = county or address_3 = county or address_4 = county or city = county then '' Else County END COUNTY FROM ( --This looks at a field and if its empty it will push the value up a field. select c.id ,case when c.address_1 = '' then c.address_2 when c.address_1 = '' and c.address_2 = '' then c.address_3 when c.address_1 = '' and c.address_2 = '' and c.address_3 = '' then c.address_4 when c.address_1 = '' and c.address_2 = '' and c.address_3 = '' and c.address_4 = '' then c.city when c.address_1 = '' and c.address_2 = '' and c.address_3 = ''and c.address_4 = '' and c.city = '' then c.county Else c.Address_1 End Address_1 ,case when c.address_2 = '' and c.address_3 = '' and c.address_4 = '' and c.city = '' then c.county when c.address_2 = '' and c.address_3 = '' and c.address_4 = '' then c.city when c.address_2 = '' and c.address_3 = '' then c.address_4 When c.address_1 = c.address_2 or c.address_2 = '' then c.address_3 Else c.address_2 End Address_2 ,case when c.address_3 = '' and c.address_4 = '' and c.city = '' then c.county when c.address_3 = '' and c.address_4 = '' then c.city when c.address_2 = c.address_3 or c.address_3 = '' then c.address_4 else c.address_3 End Address_3 ,case when c.address_4 = '' and c.city = '' then c.county when c.address_3 = c.address_4 or c.address_4 = '' then c.city else c.address_4 End Address_4 ,case --when c.address_4 = c.city then ' ' when c.city = '' and c.county = '' then Null when c.address_4 = c.city or c.city = '' then c.county else c.city End City ,case when c.city = c.county then ' ' when c.county = '' then Null Else c.county End County from cm_customers_TEST c where c.id = 99999999 )SUBQ
-- ============================================= -- Author: Gary Janecek -- Create date: 4/19/2010 -- Description: Returns the uiOrderStatePK of the specified OrderState -- ============================================= ALTER PROCEDURE [dbo].[sys_GetOrderStatePK] @vcOrderState varchar(75) ,@uiOrderStatePK uniqueidentifier OUTPUT AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Insert statements for procedure here SET @uiOrderStatePK = (SELECT uiOrderStatePK FROM tblOrderState WHERE UPPER(vcOrderState) = UPPER(@vcOrderState)) END
DECLARE @uiTransmitOrderStateFK uniqueidentifier EXEC sys_GetOrderStatePK 'OrderTransmittedByServer', @uiOrderStatePK = @uiTransmitOrderStateFK OUTPUT PRINT @uiTransmitOrderStateFK
First, you must create an Event handler for when the drop down button menu ITEM is clicked. Then, in the Click Event handler, copy the clickedMenuItem's Text to the button's Text.
/* Get the button element and call a function to create Click Even handlers for each menu item. */ private void InitializeEventHandlers() { RadDropDownButtonElement buttonElement = (RadDropDownButtonElement)this.radDropDownButton1.RootElement.Children[0]; radDropDownButton1SubscribeMenuItems(buttonElement.DropDownMenu.Items); } /* For Each of the menu items in the drop down button, Create a Click Event handler for the menu item. */ private void radDropDownButton1SubscribeMenuItems(RadItemCollection menuItems) { for (int i = 0; i < menuItems.Count; i++) { RadMenuItem subMenuItem = menuItems[i] as RadMenuItem; if (subMenuItem != null) { if (subMenuItem.Items.Count == 0) subMenuItem.Click += new EventHandler(radDropDownButton1MenuItem_Click); else radDropDownButton1SubscribeMenuItems(subMenuItem.Items); } } } /*When the Click event fires, copy the clickedMenuItem's Text to the button's Text. */ private void radDropDownButton1MenuItem_Click(object sender, EventArgs e) { RadMenuItem clickedMenuItem = (RadMenuItem)sender; this.radDropDownButton1.Text = clickedMenuItem.Text; }
/* How to fill a radDropDownButton and create events for each menuitem. */
private void FillradDropDownButtonSelectSite(UserSecurity myUserSecurity)
{
try
{
radDropDownButtonSelectSite.Items.Clear();
foreach (UserSite site in myUserSecurity.LoginSites)
{
Telerik.WinControls.UI.RadMenuItem LoginToSite = new Telerik.WinControls.UI.RadMenuItem();
//if (!myUserSecurity.CurrentlyLoggedInSiteIndex.Equals(site.SiteID))
//{
LoginToSite.Text = site.SiteDescription;
LoginToSite.Tag = site.SiteID;
radDropDownButtonSelectSite.Items.Add(LoginToSite);
LoginToSite.Click += new System.EventHandler(LoginToSite_Click);
//}
}
}
catch (Exception ex)
{
//Log error
//TwoToad.ToadLib.Windows.Log.Error(ex);
MessageBox.Show(ex.ToString());
return;
}
}
To set the background color of a RadTextBox control at design time:
- Select the RadTextBox control and open its Smart Tag
- Select the RadTextBoxItem node from the tree on the left and change its BackColor property from the grid on the right.
- Select the FillPrimitive element from the tree on the left and change its BackColor property again from the grid on the right. You should note that the GradientStyle property of the FillPrimitive should be set to Solid.
/* To set the background color of a RadTextBox control at run time: */ ... SetRadTextBoxBackgroundColor(RadTB, System.Drawing.Color.Pink); ... private static Color SetRadTextBoxBackgroundColor(RadTextBox RadTB, Color BackgroundColor) { ((Telerik.WinControls.UI.RadTextBoxItem)(RadTB.GetChildAt(0).GetChildAt(0))).BackColor = BackgroundColor; ((Telerik.WinControls.Primitives.FillPrimitive)(RadTB.GetChildAt(0).GetChildAt(1))).BackColor = BackgroundColor; return BackgroundColor; }
/* How to fill a radDropDownButton and create events for each menuitem. */
private void FillradDropDownButtonSelectSite(UserSecurity myUserSecurity)
{
try
{
radDropDownButtonSelectSite.Items.Clear();
foreach (UserSite site in myUserSecurity.LoginSites)
{
Telerik.WinControls.UI.RadMenuItem LoginToSite = new Telerik.WinControls.UI.RadMenuItem();
//if (!myUserSecurity.CurrentlyLoggedInSiteIndex.Equals(site.SiteID))
//{
LoginToSite.Text = site.SiteDescription;
LoginToSite.Tag = site.SiteID;
radDropDownButtonSelectSite.Items.Add(LoginToSite);
LoginToSite.Click += new System.EventHandler(LoginToSite_Click);
//}
}
}
catch (Exception ex)
{
//Log error
//TwoToad.ToadLib.Windows.Log.Error(ex);
MessageBox.Show(ex.ToString());
return;
}
}
/// <summary>
/// Formats a RadGridView control after populating with a datasource. The fieldnames of the datasource fields
/// become the column headings in the RadGridView. This method hides all columns where the field name in the
/// column.HeaderText begins with an underscore (_). If it doesn't begin with an underscore then the column remains
/// visible. In addition, all underscores in the column.HeaderText is replaced with a space ("Right_Eye_Bride_Size"
/// becomes "Right Eye Bridge Size" to make the column header more readable to the user. Finally, best fit the columns
/// in the grid.
/// </summary>
/// <param name="RGV">The RadGridView Control with a datasource.</param>
public static void FormatFriendlyUIGrid(RadGridView RGV)
{
#if DEBUG
foreach (GridViewColumn column in RGV.Columns)
{
if (column.HeaderText.StartsWith("_"))
column.IsVisible = false;
else
column.HeaderText = column.HeaderText.Replace("_", " ");
}
#endif
RGV.MasterTemplate.BestFitColumns();
}
public static void SetTextBoxToolTips(RadTextBox tb, string Value, Color BackColor)
{
SetTextBoxToolTips(tb, Value);
SetTextBoxBackColor(tb, BackColor);
}
public static void SetTextBoxToolTips(RadTextBox tb, String Value)
{
RadTextBoxElement TextBoxRootToolTipElement = ((Telerik.WinControls.UI.RadTextBoxElement)(tb.RootElement.Children[0]));
if (String.IsNullOrEmpty(Value))
{
TextBoxRootToolTipElement.TextBoxItem.AutoToolTip = false;
}
else
{
TextBoxRootToolTipElement.TextBoxItem.ToolTipText = Value;
TextBoxRootToolTipElement.TextBoxItem.AutoToolTip = true;
}
}
public static void SetTextBoxBackColor(RadTextBox tb, Color BackColor)
{
RadTextBoxElement TextBoxElement = ((Telerik.WinControls.UI.RadTextBoxElement)(tb.GetChildAt(0)));
TextBoxElement.BackColor = BackColor;
}
To change the color of a radTextBox, see Telerik: radTextBox: How to fill a radDropDownButton and create events for each menuitem.
using TwoToad.ToadLib; ... private bool validateTextBoxLength(TextBox tb, int minlength, int maxlength) { if (tb.Text.Trim().Trim().Length < minlength || tb.Text.Trim().Trim().Length > maxlength) { tb.BackColor = System.Drawing.Color.Pink; return false; } tb.BackColor = System.Drawing.SystemColors.Window; return true; }
To change the color of a radTextBox, see Telerik: radTextBox: How to fill a radDropDownButton and create events for each menuitem.
using TwoToad.ToadLib; ... private bool validateTextBoxExactLength(TextBox tb, int ExactLength) { if (tb.Text.Trim().Trim().Length != ExactLength) { tb.BackColor = System.Drawing.Color.Pink; return false; } tb.BackColor = System.Drawing.SystemColors.Window; return true; }
To change the color of a radTextBox, see Telerik: radTextBox: How to fill a radDropDownButton and create events for each menuitem.
using TwoToad.ToadLib; ... private bool validateEmailAddress(TextBox tb, bool IsRequired) { if (IsRequired || tb.Text.Trim().Length > 0) { if (!TwoToad.ToadLib.Validate.IsEmailAddress(tb.Text.Trim())) { tb.BackColor = System.Drawing.Color.Pink; return false; } tb.BackColor = System.Drawing.SystemColors.Window; } return true; }
To change the color of a radTextBox, see Telerik: radTextBox: How to fill a radDropDownButton and create events for each menuitem.
using TwoToad.ToadLib; ... private bool validateTenDigitPhoneNumber(TextBox tb) { string phonenumber = TwoToad.ToadLib.Format.PhoneNumber(tb.Text, false); if (phonenumber.Length != 12 || !TwoToad.ToadLib.Validate.IsNorthAmericanPhoneNumber(phonenumber)) { tb.BackColor = System.Drawing.Color.Pink; return false; } tb.Text = TwoToad.ToadLib.Format.PhoneNumber(tb.Text, true); tb.BackColor = System.Drawing.SystemColors.Window; return true; }
To change the color of a radTextBox, see Telerik: radTextBox: How to fill a radDropDownButton and create events for each menuitem.
using TwoToad.ToadLib; ... private bool validatePhoneNumber(TextBox tb) { string phonenumber = TwoToad.ToadLib.Format.PhoneNumber(tb.Text, false); if (!TwoToad.ToadLib.Validate.IsNorthAmericanPhoneNumber(phonenumber)) { tb.BackColor = System.Drawing.Color.Pink; return false; } tb.Text = TwoToad.ToadLib.Format.PhoneNumber(tb.Text, false); tb.BackColor = System.Drawing.SystemColors.Window; return true; }
To change the color of a radTextBox, see Telerik: radTextBox: How to fill a radDropDownButton and create events for each menuitem.
using TwoToad.ToadLib; ... private bool validateSSN(TextBox tb) { string ssn = TwoToad.ToadLib.Format.SocialSecurityNumber(tb.Text); if (!TwoToad.ToadLib.Validate.IsSocialSecurityNumber(ssn)) { tb.BackColor = System.Drawing.Color.Pink; return false; } tb.Text = ssn; tb.BackColor = System.Drawing.SystemColors.Window; return true; }
// Compute difference between Hippa dates.
TimeSpan ts = this.radDateTimePickerHippaCertificateExpires.Value - this.radDateTimePickerHippaCertifiedOn.Value;
if (ts.Days > 360)
{
this.radDateTimePickerHippaCertificateExpires.BackColor = System.Drawing.Color.Pink;
this.radDateTimePickerHippaCertifiedOn.BackColor = System.Drawing.Color.Pink;
status = false;
}
else
{
this.radDateTimePickerHippaCertificateExpires.BackColor = System.Drawing.SystemColors.Window;
}
Download the VB6 Mouse Wheel.exe file that includes the add-in DLL and the code that is used to create the add-in DLL.
Note: Save the file to the folder
C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\AddIns
The vb6mousewheel.exe file is available for download from the
Microsoft Download Center
OR
locally
For more information about how to download Microsoft support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591 How to obtain Microsoft support files from online services.
- If not already there, copy the VB6IDEMouseWheelAddin.dll to the folder
C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\AddIns - Run a Command Prompt as Administrator (Right-click Command Prompt, Run as Administrator).
- Type the following commands:
regsvr32 C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\AddIns\VB6IDEMouseWheelAddin.dll
- Start Visual Basic 6.0.
- Click Add-Ins, and then click Add-in Manager.
- In the Add-in Manager list, click MouseWheel Fix.
- Click to select the Loaded/Unloaded check box, and then click to select the Load on Startup check box.
- Click OK.
You can also build the add-in DLL in Visual Basic 6.0. If you do this, the add-in DLL is automatically registered. You can then follow steps 4 through 7 to enable the add-in DLL. To build the add-in DLL, click Make VB6IDEMouseWheelAddin.dll on the File menu.
To remove it, follow these procedures.
- Start Visual Basic 6.0.
- Click Add-Ins, and then click Add-in Manager.
- In the Add-in Manager list, click MouseWheel Fix.
- Click to UNCHECK the Loaded/Unloaded check box, and then click to UNCHECK the Load on Startup check box.
- Click OK.
- Close Visual Basic 6.0.
- Run a Command Prompt as Administrator (Right-click Command Prompt, Run as Administrator).
- Type the following commands:
regsvr32 -u VB6IDEMouseWheelAddin.dll
- Now you can remove the VB6IDEMouseWheelAddin.dll file from the folder you installed it from (C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\AddIns\VB6IDEMouseWheelAddin.dll)
For more information, click the following article to view the article in the Microsoft Knowledge Base:
Mouse wheel events do not work in the Visual Basic 6.0 IDE.
Several functions in Visual Basic 2008 behave differently than their equivalent Visual Basic 6.0 functions. In most cases, this does not have an effect on your code; however, you should be aware of these differences and review your code to make sure that your usage of these functions is still appropriate.
Array Function
In Visual Basic 6.0, the Array statement is used to return a variant
containing an array, assigning values to array elements in a single step.
The Array function is no longer supported in Visual Basic 2008.
- When a Visual Basic 6.0 project is upgraded to Visual Basic 2008, any Variant variables are converted to the Object data type, so the upgraded code will return an object containing an array.
- What to do next. Review your code. In most cases, you will probably want to create an array to replace the upgraded object and assign the values as you would with any other array.
Dir Function
In Visual Basic 6.0, the Dir function is used to return the name of a file, folder, or directory. The "." and ".." strings can be used in the path argument to represent the current directory or the encompassing directory, respectively.
- In Visual Basic 2008, the Dir function is essentially the same, but the "." and ".." syntax has a different behavior.
- What to do next. Code that returned files or directories was often written with the assumption that the "." and ".." would be returned as the first two entries; this is no longer true in Visual Basic 2008. Because of the difference in behavior, the upgraded code may not return the first two files or directories.
Get#, Put# Functions
In Visual Basic 6.0, the Get# and Put# functions are used to read and write data to a file.
- In Visual Basic 2008, these are upgraded to the FilePut and FileGet functions. When these functions are used to pass dynamic arrays or strings to a file opened in Random mode, a two-byte length descriptor is added, resulting in a different file length.
- What to do next. To achieve the same results as in Visual Basic 6.0, use the optional ArrayIsDynamic argument to the FilePut and FileGet functions.
- When opening a file in Random mode, use the StringIsFixedLength argument.
IsObject Function
In Visual Basic 6.0, the IsObject function is used to determine if a Variant variable is of type vbObject. If the variable is empty, the IsObject function returns true for an object, but false for a variant. Likewise, if the variable contains a string, it returns false.
- When a Visual Basic 6.0 project is upgraded to Visual Basic 2008, any Variant variables are converted to the Object data type. The Visual Basic 2008 IsReference function is used to determine if a variable contains an object. If an object is empty, the function still returns true because it is an object. In addition, strings in Visual Basic 2008 are objects and will return true.
- What to do next. Find the variable(s) being evaluated by the IsReference function and make sure that the logic is still valid.
Mod Operator
In Visual Basic 6.0, the Mod operator accepted any numeric expression and the result was always returned as an integer.
- In Visual Basic 2008, the Mod operator no longer accepts variants, and if either operand is a floating-point number, the result will be a floating-point number.
- What to do next. If a variant has been converted to an object during upgrade, convert it to the appropriate numeric data type.
If either of the operands is a floating-point number, modify the data type of the result, or modify your code to convert the operand(s) using the CShort function before using the Mod operator.
Return Statement
In Visual Basic 6.0, the Return statement is used to branch back to the code following a GoSub statement.
- In Visual Basic 2008, the GoSub statement is not supported. The Return statement is used to return control to a calling procedure from a Function or Sub procedure.
- What to do next. Remove any lines of code that use Return in conjunction with a GoSub statement.
SavePicture Statement
In Visual Basic 6.0, the SavePicture statement is used to save a graphic from the Picture or Image property of an object to a file. If the format of the graphic for the Picture property is either GIF or JPEG, it is saved as a bitmap file (BMP). Graphics for the Image property are always saved as bitmaps regardless of their original format.
- In Visual Basic 2008, the default behavior of the Image..::.Save method saves the files in different formats than in Visual Basic 6.0. Save takes an ImageFormat class as an optional parameter that allows you to specify the format to use.
- What to do next. Modify the upgraded code to use the Save method, as in the following example:
' Default, will save as a PNG (Portable Network Graphics) file Picture1.Image.Save("MyPicture.bmp") ' Using the optional parameter, will save as a bitmap Picture1.Image.Save("MyPicture.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
Str Function
In Visual Basic 6.0, the Str function takes a Long data type containing any valid numeric expression as an argument; date variables or literals are treated as valid numeric expressions.
- In Visual Basic 2008, the Str function takes an object containing any valid numeric expression; date variables and literals are no longer treated as valid numeric expressions.
- What to do next. If the Str function uses a date variable or date literal as an argument, use the Format function instead. For more information, see Format Function.
TypeName Function
In Visual Basic 6.0, the TypeName function is used to return a string describing the underlying data type of a variable.
- The data types returned by the TypeName function may have different values in Visual Basic 2008. For example, any Variant variables are converted to the Object data type, strings are objects in Visual Basic 2008, and some controls return a different type. For more information, see TypeName Function (Visual Basic).
- What to do next. Compare the result of the TypeName function with the result in the Visual Basic 6.0 to determine if they are the same, and modify your code if necessary.
TypeOf Function
In Visual Basic 6.0, the TypeOf function is used in an If...Then...Else statement to determine whether an object reference is of a specified object type. In this context, a user-defined type is considered to be an object type.
- In Visual Basic 2008, user-defined types (now known as structures) are not object types and cannot be evaluated by the TypeOf function.
- The following example demonstrates the use of TypeOf with a user-defined type:
' Visual Basic 6.0 Private Type MyType a As Integer End Type Private Sub Form_Load() Dim m As MyType If TypeOf m Is MyType Then MsgBox "MyType" End If End Sub ' After upgrade to Visual Basic 2008 Private Structure MyType Dim a As Short End Structure Private Sub Form_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load Dim m As MyType ' UPGRADE_WARNING: TypeOf has a new behavior. If TypeOf m Is MyType Then MsgBox "MyType" End If End Sub
- What to do next. Modify your code to do a type comparison without the TypeOf function:
' Modified code Dim m As MyType Dim mTest As MyType If m.GetType Is mTest.GetType Then ...
VarType Function
In Visual Basic 6.0, the VarType function is used to return an enumeration representing the underlying data type of a variable declared as a variant.
- When a Visual Basic 6.0 project is upgraded to Visual Basic 2008, any Variant variables are converted to the Object data type. In Visual Basic 6.0, an unassigned variant returns 0 (Empty); in Visual Basic 2008, an unassigned object returns 9 (Object).
- What to do next. Determine if the VarType function is returning 9 and, if so, modify your code to correctly interpret the new result.
- Download vs6sp6.exe
- Run the file from the download directory.
When prompted, select the same directory you created on your computer.
You will be expanding the contents of the EXE into this directory.
- Run SetupSP6.exe from the download directory. When you accept the terms of the electronic End User License Agreement (EULA) the
setup software will replace the appropriate files in your Visual Basic 6.0, Visual C++ 6.0 and/or Visual Source Safe installation.
By default, VB.NET does not do shortcut evaluations of logical conditionals. To force them you must use OrElse or AndAlso.
Dim y as Variant = DbNull If True OR y Then ' Both Expressions will be evaluated, this statement will throw an exception when evaluating y If True ORELSE y Then ' Since Expression1 evaluates to True, y will not be evaluated If True AND y Then ' Both Expressions will be evaluated, this statement will throw an exception when evaluating y If True ANDALSO y Then ' Since Expression1 evaluates to True, y will be forced to be evaluated which will throw an exception If False ANDALSO y Then ' Since Expression1 evaluates to False, y will NOT be evaluated
15+ Free Visual Studio Add-Ins Part 1
15+ Free Visual Studio Add-Ins Part 2
Free LINQ to SQL Debug Visualizer - Scott GU’s Blog
Free ASP.NET Refactoring Add-in for Visual Studio Developers
Attach to what? To the process you want to debug, of course.
Use JustAttach!
How many developers attach to and debug arbitrary processes running on their machines? Very few, I’d imagine. And I’d think that even those few people typically prefer Windbg or an equivalent debugger to the one supplied with Visual Studio.
Which means that aside from ASP.NET developers, almost all of us using Visual Studio attach to the application that we are working on and nothing else. To attach:
1. You summon the “Attach to Process” dialog by hitting Ctrl + Alt + P. Or, if you are a mouse person, you go to Debug –> Attach to Process.
2. You search for your application in the list of processes shown and select it.
3. You optionally change some settings and then hit OK.
The second step can be particularly annoying, especially if the name of your application starts with a particularly common letter that occurs in the latter half of the English alphabet (it’s a tie between ‘s’ and ‘v’ on my machine). Even otherwise, if you’ve worked on the application for a significant amount of time, the keystrokes to select it becomes part of muscle memory (down arrow, down arrow, Enter, for e.g.,), and you occasionally end up attaching to the wrong application because some other process sneaked in. Surely there must be a better way?
Enter JustAttach – a macro that does just that. It finds out the output file path of the startup project of your solution and automatically attaches to it.
The full macro code is at the end of the blog post. You can also download, unzip, open Macro Explorer (View –> Other Windows –> Macro Explorer) and select Load Macro Project to start using it right away.
Do your fingers a favor by binding the command to a VS shortcut (Tools –> Options –> Keyboard, type JustAttach in the textbox and choose a shortcut like Ctrl + Alt+ Y); your fingers will thank you for it :).
1: Imports System 2: Imports EnvDTE 3: Imports EnvDTE80 4: Imports EnvDTE90 5: Imports System.Diagnostics 6: 7: Public Module SenthilMacros 8: Public Sub JustAttach() 9: Dim solutionBuild As SolutionBuild = DTE.Solution.SolutionBuild 10: Dim startupProjectName As String = solutionBuild.StartupProjects(0) 11: 12: If String.IsNullOrEmpty(startupProjectName) Then 13: MsgBox("Could not attach because the startup " & _ "project could not be determined", _ MsgBoxStyle.Critical, "Failed to Attach") 14: Return 15: End If 16: 17: Dim startupProject As Project = FindProject(startupProjectName.Trim()) 18: Dim outputFilePath As String = FindOutputFileForProject(startupProject) 19: 20: If String.IsNullOrEmpty(outputFilePath) Then 21: MsgBox("Could not attach because output file path " & _ "for the startup project could not be determined", _ MsgBoxStyle.Critical, "Failed to Attach") 22: Return 23: End If 24: 25: Attach(outputFilePath) 26: End Sub 27: Sub Attach(ByVal file As String) 28: Dim process As EnvDTE.Process 29: 30: For Each process In DTE.Debugger.LocalProcesses 31: If process.Name = file Then 32: process.Attach() 33: Return 34: End If 35: Next 36: 37: MsgBox("Could not attach because " + file + _ " is not found in the list of running processes", _ MsgBoxStyle.Critical, "Failed to Attach") 38: End Sub 39: 40: Function FindProject(ByVal projectName As String) As Project 41: Dim project As Project 42: For Each project In DTE.Solution.Projects 43: If project.UniqueName = projectName Then 44: Return project 45: End If 46: Next 47: End Function 48: Function FindOutputFileForProject(ByVal project As Project) As String 49: Dim fileName As String = _ project.Properties.Item("OutputFileName").Value.ToString() 50: Dim projectPath As String = _ project.Properties.Item("LocalPath").Value.ToString() 51: 52: Dim config As Configuration = _ project.ConfigurationManager.ActiveConfiguration 53: Dim buildPath = config.Properties.Item("OutputPath").Value.ToString() 54: 55: If String.IsNullOrEmpty(fileName) Or String.IsNullOrEmpty(projectPath) Then 56: Return "" 57: End If 58: 59: Dim folderPath As String = System.IO.Path.Combine(projectPath, buildPath) 60: Return System.IO.Path.Combine(folderPath, fileName) 61: 62: End Function 63: End Module
Argh! I wish I had found this one in time for the book. A second edition, maybe? I’d hate to be known as a one-hit wonder. I’m sure there are more people who could use scholarship money.
Ever did a Find in Files and was annoyed that Visual Studio showed the entire file path, forcing you to scroll over just to see the name of the file and the search result?
Here’s what you can do, among some other tweaks. Note: These involve modifying registry settings. Please use at your own risk! Also Note: You don’t have to restart Visual Studio to pick up on your registry changes. Sweet!!!
- Go to HKCU\Software\Microsoft\VisualStudio\9.0\Find
- Add a new string called Find result format with a value of
$f$e($l,$c):$t\r\n where
$f is the filename
$e is the extension
$l is the line
$c is the column
$t is the text on the line
Now let’s take a look at that Find Results window again:
And here’s the full list of items you can specify in the registry
Files
$p = path
$f = filename
$v = drive/unc share
$d = dir
$n = name
$e = .ext
Location
$l = line
$c = col
$x = end col if on first line, else end of first line
$L = span end line
$C = span end col
Text
$0 = matched text
$t = text of first line
$s = summary of hit
$T = text of spanned lines
Char
\n = newline
\s = space
\t = tab
\\ = slash
\$ = $
To Auto-Generate an Event Handler and Method, start coding your event as follows:
this.radButton.Click += [then press TAB a copule of times to generate] this.radButton.Click += new EventHandler(radButton_Click); [and] ... void radButton_Click(object sender, EventArgs e) { throw new NotImplementedException(); }
Ctrl+Shift+R to record a new temporary macro. Press Ctrl+Shift+R to stop recording. Press Ctrl+Shift+P to play the recorded macro.
Ctrl+Shift+V cycles through the clipboard ring. You can copy/cut multiple times from one are of code, then go to another area and paste them one after another.
The Toolbox (Ctrl+Alt+X) window has multiple tabs. You can drag and drop code onto this window and copy it elsewhere. Some tabs do not allow dropping code into them; those that allow will have the appropriate icon. The General tab works for me.
Ctrl+- (i.e. Ctrl + Hyphen). This cycles you through the code positions you visited. Ctrl+Shift+- to navigate in the opposite direction.
Ctrl+] takes you to the matching brace. It also takes you to the matching comment, region or quote depending on what is at the cursor now.
Press Alt and then select the area yo uwant with your mouse.
If you have many source code windows open, you can group them logically using tab groups. Right click the tab of the code window and choose New Horizontal Tab Group. This will move the window into a split window, allowing you to see both files. You can add more files to this new tab group and also move files back to the previous group by choosing Move To Previous Tab Group.
The Task List window (Ctrl+Alt+K) allows you to keep track of the things you have to do. Right click on the Task List window and choose Show Tasks|All to see a list of tasks. Ctrl+Shift+F12 to cycle through your list of tasks.
By default, comments marked with a TODO will appear in the task list.
You can add your own set of comment tokens (like the TODO comment token). Go to Tools|Options|Environment|Task List|Comment Tokens and make your changes. You can change the priority appearance of each comment token too.
Add a shortcut to the task list with Ctrl+K, Ctrl+H. This will add the current line to the task list.
Press Ctrl+Space or Alt+RightArrow to auto-complete the word. Intellisense suggestions may pop up a window if there is more than one possibility.
Press Ctrl+Shift+Space to bring up the intellisense suggestions window. When giving parameters for functions, I often need to escape the suggestions window to check another part of code. To bring it back, I used to delet a comma and then type it again; but this is easier.
Ctrl+R, Ctrl+R or Tools|Options|Text Editor|All Languages|General|Word Wrap If you want to set this option for only one language, then choose the appropriate language instead of All Languages.
Tools|Options|Text Editor|All Languages|General|Line Numbers. If you want to set this option for only one language, then choose the appropriate language instead of All Languages.
Your IDE also functions as a browser. To see your list of favorites, press Ctrl+Alt+F or choose View|Other Windows|Favorites.
- Create/Remove Bookmark - Ctrl+K, Ctrl+K
- Move to Next Bookmark - Ctrl+K, Ctrl+N
- Move to Previous Bookmark - Ctrl+K, Ctrl+P
- Clear all Bookmarks - Ctrl+K, Ctrl+L
- Auto-format selection - Ctrl+K, Ctrl+F
- Convert to lower case - Ctrl+U
- Convert to upper case - Ctrl+Shift+U
- Comment selection - Ctrl+K, Ctrl+C
- UnComment selection - Ctrl+K, Ctrl+U
- Fold/Unfold the current code block - Ctrl+M, Ctrl+M
- Unfold All - Ctrl+M, Ctrl+L
- Stop outlining - Ctrl+M, Ctrl+P
- Fold all - Ctrl+M, Ctrl+O
- Build - Ctrl+Shift+B
- Run - Ctrl+F5
- Debug - F5
- Cycle through build errors - F8
Keep in mind with the Dock property is that the order in which the controls are added to the form can affect the way that they dock. For instance, if you add ControlA to the form, instruct it to dock Fill, then you add ControlB to the form and instruct it to dock Top, ControlB will appear to cover up the top portion of ControlA. The reason for this is that ControlB is considered to be "in front" of ControlA since it was added after ControlA. To fix this situation you must right click ControlA in Visual Studio and choose Bring To Front on the context menu. This will bring ControlA to the front of ControlB and the controls will then act as expected.
- Create a New Project using the WCF Service Library template.
Name it ProductService.
- Add a Web.config file.
- Rename the Service1.cs file to ProductsService.cs
- Rename the IService1.cs file to IProductsService.cs
- Open the code view of IProductsService.cs.
- Decide what you will publish in your service.
- Use DataContract/DataMember to declare your data class objects to the service.
- Use ServiceContract/OperationContract to declare your Methods to the service.
- Do NOT include the actual code for the methods.
- Implementing the Service.
- Open the ProductService.cs class file.
- Rename the ProductService class to ProductServiceImpl
- Develop the Methods which will be exposed via the service.
Listing: ProductService.cs ... namespace ProductService { /* NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in App.config. */ public class ProductServiceImpl : IProductService { public List<string> ListProducts() { // Read the configuration information for connecting to // the AdventureWorks database Database dbAdventureWorks = DatabaseFactory.CreateDatabase("AdventureWorksConnection"); // Retrieve the details of all products by using a DataReader string queryString = @"SELECT ProductNumber FROM Production.Product"; IDataReader productsReader = dbAdventureWorks.ExecuteReader(CommandType.Text, queryString); // Create and populate a list of products List<string> productsList = new List<string>(); while (productsReader.Read()) { string productNumber = productsReader.GetString(0); productsList.Add(productNumber); } //Return the list of products return productsList; } public Product GetProduct(string productNumber) { Database dbAdventureWorks = DatabaseFactory.CreateDatabase("AdventureWorksConnection"); // Retrieve the details of the selected product by using a DataReader string queryString = @"SELECT ProductNumber, Name, Color, ListPrice FROM Production.Product WHERE ProductNumber = '" + productNumber + "'"; IDataReader productsReader = dbAdventureWorks.ExecuteReader(CommandType.Text, queryString); // Create and populate a product Product product = new Product(); if (productsReader.Read()) { product.ProductNumber = productsReader.GetString(0); product.Name = productsReader.GetString(1); if (productsReader.IsDBNull(2)) { product.Color = "N/A"; } else { product.Color = productsReader.GetString(2); } product.ListPrice = productsReader.GetDecimal(3); } //Return the product return product; } public int CurrentStockLevel(string productNumber) { Database dbAdventureWorks = DatabaseFactory.CreateDatabase("AdventureWorksConnection"); // Obtain the current stock level of the selected product // The stock level can be found by summing the quantity of the product // available in all bins in the ProductInventory table // The ProductID value has to be retrieved from the Product table string queryString = @"SELECT SUM(Quantity) FROM Production.ProductInventory WHERE ProductID = (SELECT ProductID FROM Production.Product WHERE ProductNumber = '" + productNumber + "')"; int stockLevel = (int)dbAdventureWorks.ExecuteScalar(CommandType.Text, queryString); //Return the current stock level return stockLevel; } public bool ChangeStockLevel(string productNumber, int newStockLevel, string shelf, int bin) { Database dbAdventureWorks = DatabaseFactory.CreateDatabase("AdventureWorksConnection"); // Modify the current stock level of the selected product // The ProductID value has to be retrieved from the Product table string updateString = @"UPDATE Production.ProductInventory SET Quantity = Quantity + " + newStockLevel + "WHERE Shelf = '" + shelf + "'" + "AND Bin = " + bin + @"AND ProductID = (SELECT ProductID FROM Production.Product WHERE ProductNumber = '" + productNumber + "')"; int numRowsChanged = (int)dbAdventureWorks.ExecuteNonQuery(CommandType.Text, updateString); // If no rows were updated, return false to indicate that the input // parameters did not identify a valid product and location // Otherwise return true to indicate success return (numRowsChanged != 0); } }
- Build the project.
- Configuring, Deploying and Testing the WCF Service.
- Open the Properties pages for the project.
- Click the Build tab. In the Output section of the page, change the Output path property to bin.
- Click Save All
- Add a new Text File template to the project. Name the file ProductsService.svc. The name of this file must be the same name of the Web Service and have the .svc suffix.
- Add the following code to the ProductsService.svc file. The Service attribute of the ServiceHost directive specifies the namespace (Products) and
the class (ProductsServiceImpl) that implements the service. The Assembly directive specifies
the name of the assembly (ProductsService) containing this namespace and class. - Edit the Web.config file. Add the following sections shown in bold.
- Build the Solution.
- You can now deploy the service to IIS by creating a virtual folder. You must also ensure that
the account used to run the code for the Web service, the local ASPNET account on your computer
by default, has sufficient rights to access the contents of this folder. - Deploy the WCF service to IIS (Windows Vista only)
- In the Windows Control Panel, click System and Maintenance, click Administrative
Tools, and then double-click Internet Information Services (IIS) Manager.
The Internet Information Services (IIS) Manager starts. - In the Internet Information Services (IIS) Manager, expand the node corresponding to
your computer in the tree-view, and then expand Web sites. - Right-click Default Web Site, and then click Add Application.
The Add Application dialog box appears. - In the Add Application dialog box, in the Alias text box type ProductsService.
- Click the browse button (with the ellipses “…”) adjacent to the Physical path text box. In
the Browse for Folder dialog box, select the folder Microsoft Press\WCF Step By
Step\Chapter 1\ProductsService\ProductsService under your \My Documents folder,
click then click OK. - In the Add Application dialog box, click OK.
The ProductsService Web application should appear under the Default Web site node in
the Internet Information Services (IIS) Manager. - Close the Internet Information Services (IIS) Manager.
- In the Windows Control Panel, click System and Maintenance, click Administrative
- Deploy the WCF service to IIS (Windows Vista only)
- On the Windows Start menu, click Internet Explorer.
- In the Address bar, type the address http://localhost/ProductsService/
ProductsService.svc, and then click Go. This page describes how you can obtain the metadata describing the service and use this
information to help build a client application.
- Building a WCF Client
- Add a new Console Application template project to the solution. Name it ProductsClient<.span>.
- Add a referenct to the System.ServiceModel assembly to the ProductsClient project
- On the Project menu, click Add Service Reference. In the Add Service Reference dialog
box, type http://localhost/ProductsService/ProductsService.svc?wsdl for the service
URL, type ProductsService for the service reference name, and then click OK. - Open the codeview for the ProductsClient.app.config file.
- Display the Program.cs file for the ProductsClient project in the code view window. Add the following statements to the top of the file
using System.ServiceModel; using ProductsClient.ProductsService;
- In the Main() method, add the following statements.
// Create a proxy object and connect to the service ProductsServiceClient proxy = new ProductsServiceClient("BasicHttpBinding_IProductsService"); // Test the operations in the service // Obtain a list of all products Console.WriteLine("Test 1: List all products"); string[] productNumbers = proxy.ListProducts(); foreach (string productNumber in productNumbers) { Console.WriteLine("Number: " + productNumber); } Console.WriteLine(); // Fetch the details for a specific product Console.WriteLine("Test 2: Display the details of a product"); Product product = proxy.GetProduct("WB-H098"); Console.WriteLine("Number: " + product.ProductNumber); Console.WriteLine("Name: " + product.Name); Console.WriteLine("Color: " + product.Color); Console.WriteLine("Price: " + product.ListPrice); Console.WriteLine(); // Query the stock level of this product Console.WriteLine("Test 3: Display the stock level of a product"); int numInStock = proxy.CurrentStockLevel("WB-H098"); Console.WriteLine("Current stock level: " + numInStock); Console.WriteLine(); // Modify the stock level of this product Console.WriteLine("Test 4: Modify the stock level of a product"); if (proxy.ChangeStockLevel("WB-H098", 100, "N/A", 0)) { numInStock = proxy.CurrentStockLevel("WB-H098"); Console.WriteLine("Stock changed. Current stock level: " + numInStock); } else { Console.WriteLine("Stock level update failed"); } Console.WriteLine();
- Save the Project and Build the Solution
- Run the client application
- Set the ProductsClient project as the Start-Up Project
- Run the Project
<%@ServiceHost Service="Products.ProductsServiceImpl" %> <%@Assembly Name="ProductsService" %>
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary. Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" /> </configSections> <dataConfiguration defaultDatabase="AdventureWorksConnection" /> <connectionStrings> <add name="AdventureWorksConnection" connectionString="Database= AdventureWorks;Server=(local)\SQLEXPRESS;Integrated Security=SSPI;" providerName="System.Data.SqlClient" /> </connectionStrings> <system.serviceModel> <services> <service name="Products.ProductsServiceImpl" behaviorConfiguration="ProductsBehavior"> <endpoint address="" binding="basicHttpBinding" contract="Products.IProductsService" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="ProductsBehavior"> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
Listing: IProductsService.cs ... namespace ProductService { /* NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in App.config. */ [ServiceContract] public interface IProductService { [OperationContract] ListListProducts(); [OperationContract] CompositeType GetDataUsingDataContract(CompositeType composite); // TODO: Add your service operations here } // Use a data contract as illustrated in the sample below to add composite types to service operations [DataContract] public class Product { [DataMember] public string Name; [DataMember] public string ProductNumber; [DataMember] public string Color; [DataMember] public decimal ListPrice; } }