thoughts on programming and computer related stuff RSS 2.0
# Tuesday, December 09, 2008
Often I have had problems logging in to remote desktops because the two user sessions Microsoft allows you to have are occupied. This is very annoying and until Windows Server 2008, you got no choice to log of the other users. There is however a smart little command line tool to do this.

To see logged in users, type: qwinsta /server:SERVERNAME
To log out an existing session, type: rwinsta /server:SERVERNAME SESSIONNAME

Here is an example from my machine:
C:\Users\gm>qwinsta /server:kraftwerk
 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
 services                                    0  Disc
 console                                     1  Conn
 rdp-tcp#0         gm                        2  Active  rdpwd
 rdp-tcp                                 65536  Listen
C:\Users\gm>rwinsta /server:kraftwerk rdp-tcp#0

Tuesday, December 09, 2008 5:35:12 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
Windows Server
# Monday, December 08, 2008
Last week I had to make a SQL Procedure go faster and a new join in the same operation. From the execution plan I could see that the thing that cost most time was a call to an external function made as a .NET CLR that got all the groups a person was member of, and returned it as a comma separated string. This tok a couple of milliseconds, each time, and with some of the users input resulting in over 8000 calls in a single statement, the procedure took to long time. I also had the requirement to add an other column in the result, showing a comma separated list of functions each persons had. Doing this the same way as before, would turn the procedure almost twice as sluggish as before.

To get the result wanted, a small trick was used. Here is a simplified version of what I wrote:
SELECT TOP 10
        substring(O.Functions,2,500)
FROM    dbo.Tp_Person P
CROSS APPLY ( SELECT    ',' + CAST(FunctionName AS varchar) AS [text()]
              FROM      dbo.Tp_Function F
              WHERE     F.Personid = P.Personid
              FOR XML PATH('')
             ) O( Functions )


This trick actually reduced the time of the procedure on 5000 people from about 30 seconds to 1,5 seconds. Made my day.

Monday, December 08, 2008 6:55:56 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
T-SQL
# Friday, October 31, 2008
This week I finally got around to install Windows Server 2008 on my laptop. I have a HP Compaq 6910p laptop, which is a good laptop with 64 bit dual core processor and 4 gb of RAM.

Since I have a 64-bit CPU and have been running Vista 64 for some time without any problems, I installed the 64 bit enterprise edition.

I followed the blogpost: Using Windows Server 2008 as a SUPER workstation OS to get the OS configured. Which got me pretty far, but not all the way there.

For drivers I downloaded the Vista drivers from HP's support page. They worked good except for the bluetoouth driver. But apparently, Microsoft has decided that bluetooth is not for servers, so there is no support. Both my bluetooth mouse and keyboard works with the supplied dongle, but not with the built in device.

I also turned of Internet Explorer Enhanced Security, which is nice on a production server, but extremly annoying on your desktop. This is done in Server Manager - Security Information - Configure IE ESC.

I also use virtual pc's a bit and figured Hyper-V would be cool instead of Virtual PC or Virtual Server, but when I activated this, the sleep function on my laptop no longer worked. I did find a good hack for enabling sleep with Hyper-V. Works ok, but it's not 100% ideal solution.

The current version of Live Messenger would not install either, but the MSI-version of Messenger 8.1 would install. Apparantly you can also copy the installed files from a Vista machine to get newer versions running, but I haven't tried.

Visual Studio 2008, SQL Server 2008, Office 2007, Firefox, Daemon tools all installed wihout any problems.

Final thoughts
All in all, I am very happy with my transition to Server 2008. It seems faster than Vista, and the fact that you have to turn all the bloat on instead of the opposite makes it great.

Update: I got bluetooth devices working using this blog post: Installing the Microsoft Bluetooth Stack on Windows Server 2008

Friday, October 31, 2008 1:45:09 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
Windows Server
# Tuesday, October 28, 2008
Today I got an error on a web application after upgrading it from .Net 2.0 and Visual Studio 2005 to .Net 3.5. The project uses Telerik radcontrol, a few releases old version. After upgrading, every page that uses the radcontrol DatePicker failed to load, and the dreaded "Yellow screen of death" was shown instead.

It wasen't my code that failed, it was the radcontrols own prerender-event that threw the exception. Since I don't have the source code for this control and due to the fact that the fault only appaired on one test server without Visual Studio installed, it was hard to debug. Luckily a colleague had experienced a similair problem some weeks ago, and I remembered that changing the locale settings helped him (He is swedish, and used a swedish locale in an otherwise homogenic norwegian development team).

I logged in to the server and tried to change the system locale of the admin user. No help.
I tried to change the user running the application pool from NETWORK SERVICE to the admin I logged in as. Suddenly everything worked.

I did however want to run the process as NETWORK SERVICE and not administrator or have to make another account just for this reason. Therefore I wanted to change the network services locale settings, but since this is a user you can't log in as, this seemed hard.

Luckily I found this blog post: IIS6: Changing the Locale ID when Regional Settings Won't Work
I followed the description to change the settings. For some reason this didn't quite work. Probably due to a typo. I tried to export the regedit settings for HKEY_USERS\S-1-5-20 and just manually change the sShortDate, from the English setting and to norwegian settings. Now everything is working again!

Tuesday, October 28, 2008 8:20:13 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
.NET | ASP.NET
# Thursday, October 23, 2008

Checking if a email addresses is valid in SQL can be very convinient from time to time. Here are two ways to do it in SQL, and a bit about them.

 

Here is a full SQL way to do this:

 

Create function VALIDEMAIL(@s varchar(255)) 
--Returns true if the string is a valid email address.
returns bit
as
BEGIN
DECLARE @u VARCHAR(60), @v VARCHAR(60), @x VARCHAR(60), @i int, @j int, @result bit
SET @result=1
set @s = rtrim(ltrim(@s))
SET @i=len(@s)-CHARINDEX('@',reverse(@s))+1
if @i <= 1 or len(@s) < 5
begin
  set @result = 0
  goto done
end
SET @u=LEFT(@s,@i-1)
SET @j=len(@s)-CHARINDEX('.',reverse(@s))+1
SET @v=RIGHT(@s,LEN(@s)-@j)
if @j < 3 or @j < @i
begin
  set @result = 0
  goto done
end
SET @x=substring(@s,@i+1,@j-@i-1)
IF LEN(@x)<2
 BEGIN
 SET @result=0
 GOTo done
 END
IF (LEN(@x)=3) AND (@x NOT LIKE '[a-zA-Z][a-zA-Z][a-zA-Z]'Collate  Latin1_General_BIN)
 BEGIN
 SET @result=0
 GOTo done
 END
IF (LEN(@x)=2) AND (@x NOT LIKE '[a-zA-Z][a-zA-Z]' Collate  Latin1_General_BIN)
 BEGIN
 SET @result=0
 GOTo done
 END
SET @i=1
WHILE (@i<LEN(@u))
 BEGIN
 IF SUBSTRING(@u,@i,1) NOT LIKE '[a-zA-Z0-9_\-.+=/!#$&''*%?^`{|}"@\\ ]' escape '\' Collate  Latin1_General_BIN
  BEGIN
  SET @result=0
  GOTo done
  END
 SET @i=@i+1
 END
SET @i=1
WHILE (@i<LEN(@v))
 BEGIN
 IF SUBSTRING(@v,@i,1) NOT LIKE '[a-zA-Z]' Collate Latin1_General_BIN
  BEGIN
  SET @result=0
  GOTo done
  END
 SET @i=@i+1
 END
SET @i=1
WHILE (@i<LEN(@x))
 BEGIN
 IF SUBSTRING(@x,@i,1) NOT LIKE N'[a-zA-Z\-.0-9]' escape '\' Collate  Latin1_General_BIN
  BEGIN
  SET @result=0
     goto done
  END
 SET @i=@i+1
 END
done:
return @result
END
GO

Here is another way, where you insert .NET CLR code in the database. Here I use the .NET RegEx.Ismatch, so I can use it for tons of other stuff as well with the right input.


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Text.RegularExpressions;

namespace SQLSignature
{
    public class SqlFunctions
    {

        [SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.None)]
        public static SqlBoolean fn_RegexIsMatch(SqlString input, SqlString pattern)
        {
            return (SqlBoolean)Regex.IsMatch(input.Value, pattern.Value);
        }

    }
}
In SQL:
CREATE ASSEMBLY SQLSignature
FROM 'C:\CLR Assemblies\Performance\SQLFunctions\bin\SQLFunctions.dll';
GO
-- Create fn_SQLSigCLR and fn_RegexReplace functions
CREATE FUNCTION dbo.fn_RegexIsMatch(@input AS NVARCHAR(MAX),@pattern AS NVARCHAR(MAX))RETURNS BIT 
WITH RETURNS NULL ON NULL INPUT 
EXTERNAL NAME SQLSignature.SQLFunctions.fn_RegexIsMatch;
GO
This can be run with a command like:

    select *
    from [AW].[person].emailaddress as p
    where dbo.fn_RegexIsMatch(RTRIM(LTRIM(lower(P.emailaddress))),
'^[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$')=1

I did some timings on the two functions and as you can see below there are big differences. The .NET CLR one is almost 8 times faster(cpu time) than the T-SQL one. It's also a whole lot easier to read, and can be used for all other RegEx's needed. You do however need to get out of management studio to make it, and 1.5 seconds is for processing almost 20000 email addresses still should be fast enough for most uses.

SET STATISTICS TIME ON

    select *
    from [AW].[person].emailaddress as p
    where dbo.VALIDEMAIL(P.emailaddress)=1

    select *
    from [AW].[person].emailaddress as p
    where dbo.fn_RegexIsMatch(RTRIM(LTRIM(lower(P.emailaddress))),
'^[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$')=1 (19929 row(s) affected) SQL Server Execution Times: CPU time = 1466 ms, elapsed time = 1911 ms. (19972 row(s) affected) SQL Server Execution Times: CPU time = 203 ms, elapsed time = 380 ms.
It's pretty cool to see that .NET performs good within SQL as well. I am primarily a .NET developer but do have to use SQL quite a bit as well, but the fact that .NET outperforms SQL both in readability and speed inside SQL on some actions make my job a lot easier.


Thursday, October 23, 2008 8:48:20 AM (GMT Standard Time, UTC+00:00)  #    Comments [1] - Trackback
.NET | T-SQL
# Wednesday, September 03, 2008

All most every ASP.NET website I have seen, uses Databinder.Eval(Container.DataItem, "colum1") in repeaters to get the data passed in and show it on screen. The problem with Databinder.Eval is that it uses reflection to evaluate the item. This is time consuming and unnecessary, so instead, one should use casting to obtain the same effect. Try not to do it this way:

<asp:repeater id="rptAccounts" runat="server">
    <itemtemplate>
        <%# Databinder.Eval(Container.DataItem, "colum1") %> <br />
    </itemtemplate>
</asp:repeater>

But use this one instead:

<asp:repeater id="rptAccounts" runat="server">
    <itemtemplate>
        <%# ((BusinessObjects.Object)Container.DataItem).Column1 %> <br />
    </itemtemplate>
</asp:repeater>

This will also give you a compiler warning if the members of a class should change, and
not just runtime fail such as the first example. If you are not using business
objects, but a DataTable, you can  cast
to datarow and get the column right out of there like this:


<asp:repeater id="rptAccounts" runat="server">     <itemtemplate>         <%# ((DataRow)Container.DataItem)["Column1"] %> <br />     </itemtemplate> </asp:repeater>

This both increases speed and makes the application more robust to runtime errors. A win-win situation:)



Wednesday, September 03, 2008 6:42:36 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
.NET | ASP.NET
# Monday, September 01, 2008

Third party applications are great, and its very often smart to use open source or buy modules you need before making your own. However a lot of third party applications do create some problems. One is that prices and functionality can change and new, better and cheaper products come to surface.

 

Therefore, you do not want to be to dependent on these applications, so if you find another tool that does the same thing even better, you should be able to switch it out easy. A good way to do this is to create a interface and a factory pattern, and refer to the interface in your code and let the factory class decide what tool to use.  You can also use this pattern to ease mocking of objects. And let the factory return a mock object if you are unit testing.


Example in C#:

using System;

namespace Logger
{
    // An interface is created
    interface iLog
    {
        bool Log(string s);
    }
    //An implementation using enterprise libraries logging
    class EntLog : iLog 
    {
        public bool Log(string s)
        {
            //Implement logic to save to log
            return false;
        }
    }

    //An implementation using log4net to save logs.
    class log4net : iLog
    {
        public bool Log(string s)
        {
            //Implement logic to save to log
            return false;
        }
    }

    // A factory class
    class LogFactory
    {
        // Creates an object, of the right type.
        public static iLog CreateLog(){
            return new log4net();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // Get the log object to use.
            iLog logger = LogFactory.CreateLog();
            //Print the type of logger used
            Console.Out.WriteLine(logger.GetType());
            // Log a message and write the result
            Console.Out.WriteLine(logger.Log("Something is happening"));
            Console.ReadKey();
        }
    }
}

To change this to use entLog instead of log4net, all you have to do is change the object created in the logfactory.  To add a new logger, all you have to do is create a new class to implement Ilog and change the creator to return the new logger. The creator could also have a constructor that takes an input, so that you can decide in the class using the log what kind of log you want to use.

 

Monday, September 01, 2008 11:33:16 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
.NET | Patterns
# Saturday, August 23, 2008

In .NET there is a String.IsNullOrEmpty, but there is no similar thing on an Array. There should be, and there is a solution is in the new extension methods. This one works for all collections.

using System.Collections;

namespace MyExtensions
{
  public static class CollectionExtensions
  {
    public static bool IsNullOrEmpty(this ICollection col)
    {
      return (col == null || col.Count == 0);
    }
  }
}

Saturday, August 23, 2008 8:58:13 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
.NET
Navigation
Archive
<December 2008>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Gaute Magnussen
Sign In
Statistics
Total Posts: 17
This Year: 0
This Month: 0
This Week: 0
Comments: 1
Themes
Pick a theme:
All Content © 2010, Gaute Magnussen
DasBlog theme 'Business' created by Christoph De Baene (delarou)