December 2006 - Posts

Perpetuum Software

Perpetuum Software has donated a few copies of their “.NET ModelKit Suite” (http://www.perpetuumsoft.com/Product.aspx?lang=en&pid=38) to the Orlando .NET Users Group. They have offered the first 4 people that read this post and email me at software@shawnweisfeld.com a free copy of their tool suite.
Posted by sweisfeld | with no comments

VB.NET vs. C#.NET

Ok so I know that this is a heated subject but I thought I would weigh in with my opinion and hopefully add some to the conversation. The focus of my discussion is not the “syntactical sugar” as one of my colleagues calls it but actual performance. To keep things the same I wrote two chunks of code one in VB the other in C# compiled them using VS.NET in release mode and then used Reflector (http://www.aisto.com/roeder/dotnet/) to decompile the assemblies. As you can see both versions produced the same disassembly but do they produce the same performance. Conventional wisdom would say yes, but my crude benchmarking shows otherwise. This would not bother me so much if I could explain it, but I cannot. What do you think, post your comments below. . .

VB Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    Sub Main()
Dim num1 As Long = 0
Do While (num1 < 10)
Dim time2 As DateTime = DateTime.Now
Dim num2 As Long = 0
Dim num3 As Long = 0
Dim num4 As Long = 0
Dim num5 As Long = 0
Dim num6 As Long = 0
Dim num7 As Long = 0
Do While (num7 < 100000000)
num5 = ((num2 + (num3 * num4)) + num5)
num6 = (((((num4 * num3) * 12) + num2) + (num2 + (num3 * num4))) + num6)
num7 += 1
Loop
Dim span1 As TimeSpan = DirectCast((DateTime.Now - time2), TimeSpan)
Console.WriteLine("VB {1} {0:0.000} {2} {3}", New Object() {span1.TotalMilliseconds, num1, num5, num6})
num1 += 1
Loop
Console.ReadKey()
End Sub

C# Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        static void Main(string[] args)
{
for (long num1 = 0; num1 < 10; num1++)
{
DateTime time2 = DateTime.Now;
long num2 = 0;
long num3 = 0;
long num4 = 0;
long num5 = 0;
long num6 = 0;
for (long num7 = 0; num7 < 0x5f5e100; num7++)
{
num5 = (num2 + (num3 * num4)) + num5;
num6 = ((((num4 * num3) * 12) + num2) + (num2 + (num3 * num4))) + num6;
}
TimeSpan span1 = (TimeSpan)(DateTime.Now - time2);
Console.WriteLine("C# {1} {0:0.000} {2} {3}", new object[] { span1.TotalMilliseconds, num1, num5, num6 });
}
Console.ReadKey();
}

VB Code Disassembled (into C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void Main()
{
for (long num1 = 0; num1 < 10; num1++)
{
DateTime time1 = DateTime.Now;
long num2 = 0;
long num3 = 0;
long num4 = 0;
long num5 = 0;
long num6 = 0;
for (long num7 = 0; num7 < 0x5f5e100; num7++)
{
num5 = (num2 + (num3 * num4)) + num5;
num6 = ((((num4 * num3) * 12) + num2) + (num2 + (num3 * num4))) + num6;
}
TimeSpan span1 = (TimeSpan) (DateTime.Now - time1);
Console.WriteLine("VB {1} {0:0.000} {2} {3}", new object[] { span1.TotalMilliseconds, num1, num5, num6 });
}
Console.ReadKey();
}

C# Code Disassembled (into C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static void Main(string[] args)
{
for (long num1 = 0; num1 < 10; num1++)
{
DateTime time1 = DateTime.Now;
long num2 = 0;
long num3 = 0;
long num4 = 0;
long num5 = 0;
long num6 = 0;
for (long num7 = 0; num7 < 0x5f5e100; num7++)
{
num5 = (num2 + (num3 * num4)) + num5;
num6 = ((((num4 * num3) * 12) + num2) + (num2 + (num3 * num4))) + num6;
}
TimeSpan span1 = (TimeSpan) (DateTime.Now - time1);
Console.WriteLine("C# {1} {0:0.000} {2} {3}", new object[] { span1.TotalMilliseconds, num1, num5, num6 });
}
Console.ReadKey();
}

Performance results

Language Try Time Language Try Time
VB 0  6,369.35 C# 0   2,718.63
VB 1  6,353.82 C# 1   2,687.56
VB 2  6,369.35 C# 2   2,687.56
VB 3  6,369.35 C# 3   2,703.09
VB 4  6,353.82 C# 4   2,687.56
VB 5  6,369.35 C# 5   2,687.56
VB 6  6,353.82 C# 6   2,703.09
VB 7  6,369.35 C# 7   2,689.58
VB 8  6,369.35 C# 8   2,698.18
VB 9  6,353.82 C# 9   2,698.18
AVERAGE  6,363.14 AVERAGE   2,696.10
(times in milliseconds)

Posted by sweisfeld | 6 comment(s)
Filed under: , ,

Help with SSIS

UPDATE: it appears to work fine when the physical path to the file is replaced with a file share path (i.e. "\\machine\files\xxx.txt")

I recently posted the following question to the Microsoft Newsgroup. If you have any ideas please post a reply to the Newsgroup. THANKS
http://www.microsoft.com/technet/community/newsgroups/dgbrowser/en-us/default.mspx?dg=microsoft.public.sqlserver.dts&mid=61f557cb-37c7-4be1-91e5-960262653fdd

When executing a SSIS package I get the following error
The file name "D:\xxx.TXT" specified in the connection was not valid.

I am executing my package from a .NET Assembly using "Microsoft.SqlServer.Dts.Runtime"

C# excerpt
Application a = new Application();
Package p = a.LoadPackage("e:\xxx.dtsx", null);
DTSExecResult result = p.Execute();

My package does the following:
1) Executes a TSQL Statement to delete all the data from the table
2) Reads in records from a flat file on the disk (flat file source)
3) Uses Derived columns to add some information to the result set
4) Uses a OLE DB Destination to load that data into a table into SQL Server

The package is created on one computer and executed on another.

It uses integrated authentication to access the SQL Server, the nt account the application is running under has SA permissions in the sql server and is an admin on the windows server. The nt account that the SSIS service is running under is an admin on the windows server. Everyone has full control of the file. (I understand this is not the best thing from a security perspective, but I was trying to eliminate security as a cause of the package not being able to see the flat file on the disk.)

 

Posted by sweisfeld | with no comments
Filed under: ,

Beginning Oracle & .NET

A question came across my desk asking about how to get started with using Oracle in .NET. These links on the Oracle site are very helpful. Post comments to share your favorite links.

The Oracle .NET Developer Center
http://www.oracle.com/technology/tech/dotnet/index.html

Build a .NET Application on the Oracle Database
http://www.oracle.com/technology/pub/articles/cook_dotnet.html

Oracle .NET Drivers
http://www.oracle.com/technology/tech/dotnet/tools/index.html

Posted by sweisfeld | with no comments
Filed under: , ,

The “Double Hop” Issue

I have run into the dreaded “Double Hop” Issue many times over the last few years, I have even heard horror stories from developers in other companies. To that end I have decided to put together a list of useful links on this issue. Here is a few that I found helpful. If you have more please share them via the comments section.

KB Articles
http://support.microsoft.com/kb/910449
http://support.microsoft.com/kb/891031
http://support.microsoft.com/kb/810572

Web Cast
http://support.microsoft.com/servicedesks/webcasts/seminar/shared/asp/view.asp?url=/servicedesks/webcasts/en/WC102704/manifest.xml

Posted by sweisfeld | with no comments
Filed under: ,

Stack Based Flood Fill Algorithm

For a recent project I needed a Flood Fill Algorithm (see Flood Fill in Wikipedia, http://en.wikipedia.org/wiki/Flood_fill). Here is my implementation in C++.

 

Some things to note

1)      I am using the ImagerBitmapClass from a previous post (http://drowningintechnicaldebt.com/blogs/shawnweisfeld/archive/2006/11/06/Bitmap-Processing-in-C_2300_.aspx), which I converted to C++

2)      I am doing this fill in grey scale, you can easily change it to use full color objects

3)      I am looking for all white objects, converting the first blob of white pixels to a given color, then moving to the next blob with a new color


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
marker = 100;
for (int row = 0; row < iright->GetBitmapHeight(); row++)
{
  for (int column = 0; column < iright->GetBitmapWidth(); column++)
  {
    if (iright->GetGreyPixel(column, row) == 255)
    {
      System::Collections::Generic::Queue<System::Drawing::Point> q = gcnew System::Collections::Generic::Queue<System::Drawing::Point>();
      q.Enqueue(System::Drawing::Point(column, row));
      iright->SetPixel(column, row, marker);
      while (q.Count > 0)
      {
        Point p = q.Dequeue();
        if (iright->AddToStack(p.X+1, p.Y, marker))
        {
          q.Enqueue(System::Drawing::Point(p.X+1, p.Y));
          iright->SetPixel(p.X+1, p.Y, marker);
        }
        if (iright->AddToStack(p.X, p.Y+1, marker))
        {
          q.Enqueue(System::Drawing::Point(p.X, p.Y+1));
          iright->SetPixel(p.X, p.Y+1, marker);
        }
        if (iright->AddToStack(p.X-1, p.Y, marker))
        {
          q.Enqueue(System::Drawing::Point(p.X-1, p.Y));
          iright->SetPixel(p.X-1, p.Y, marker);
        }
        if (iright->AddToStack(p.X, p.Y-1, marker))
        {
          q.Enqueue(System::Drawing::Point(p.X, p.Y-1));
          iright->SetPixel(p.X, p.Y-1, marker);
        }
      }
      marker += 20;
    }
  }
}
inline bool AddToStack(int x, int y, int marker)
{
  if ((x < 0) || (x >= this->GetBitmapWidth()))
  {
    return false;
  }
  if ((y < 0) || (y >= this->GetBitmapHeight()))
  {
    return false;
  }
  int px = this->GetGreyPixel(x, y);
  if (px == 255 && px != marker)
  {
    return true;
  }
  return false;
}
Posted by sweisfeld | with no comments
Filed under: , , ,

ASP.NET AJAX Random Image Rotator

Joe Healy (http://www.devfish.net) came to Orlando today to talk about ASP.NET AJAX (http://ajax.asp.net). After seeing his presentation I was inspired to play with the tools. Additionally I got an email asking that I build an image rotator that changed the images on a webpage every 5 seconds. I thought to myself, self I can do that with AJAX, so I did, and I thought I would share it with you.

First I added a ScriptManager and UpdatePanel to the page, inside the ContentTemplate area of the UpdatePanel I added an AJAX Timer and an ASP image. Next I set the interval property to the number of milliseconds I wanted each picture to be visible. Now in the code behind I created a method that set the url property of the image to a random image from my images folder. I now call that method from the page load event and like magic you have a simple random image rotator in ASP.NET AJAX.

Thanks Joe for coming out to speak to ONETUG!

1
2
3
4
5
6
7
8
9
10
11
12
    <form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server"
Interval="5000">
</asp:Timer>
<asp:Image runat="server" ID="img" />
</ContentTemplate>
</asp:UpdatePanel>
</form>

1
2
3
4
5
6
7
8
9
10
11
12
    protected void Page_Load(object sender, EventArgs e)
{
SetNextImage();
}
private void SetNextImage()
{
string path = Server.MapPath("~/Image/");
string[] files = Directory.GetFiles(path);
Random r = new Random();
FileInfo fi = new FileInfo(files[r.Next(0, files.Length)]);
img.ImageUrl = "~/Image/" + fi.Name;
}
Posted by sweisfeld | 4 comment(s)
Filed under: , ,

16th Prize in the November 2006 Community Credit Contest



I am please to announce that I have won 16th Prize in the November 2006 Community Credit (http://www.community-credit.com/) Contest. I am the proud owner of a Mood Beams Creature. I wanted to give a big thank you to David Silverlight (http://www.xmlpitstop.com/), and all the volunteers and sponsors that make a GREAT organization like Community Credit work!

Mood Beams

These four little creatures respond to music with a variety of lightshows — heartbeat; rainbow; strobe; color dance; or color hold (a steady glow). Turn off their Beat Sensor and they'll still attempt to dazzle you with ever-changing lights of red, yellow, purple, green, orange and blue — each with its own distinctive color palette. They stand about 3 1/2" tall.
Posted by sweisfeld | with no comments