Thursday 30 May 2013

System.Random - not true random

In .NET framework, System.Random class does not offer true random behavior. If you create two instances of System.Random and invoke Next() method on each of the instances, it will return the same value.

Random random = new Random();
Random random2 = new Random();

Console.WriteLine(random.Next());
Console.WriteLine(random2.Next());

Console.WriteLine(random.Next(1, 1000000));
Console.WriteLine(random2.Next(1, 1000000));

Console.WriteLine(random.Next(1, 100000));
Console.WriteLine(random2.Next(1, 100000));

Console.WriteLine(random.Next(1, 10000));
Console.WriteLine(random2.Next(1, 10000));


However if you changed the above code to have a little wait (I used Thread.Sleep) between the steps that create the instances of Random class, then these instances produce different values.

Random random = new Random();
System.Threading.Thread.Sleep(10);
Random random2 = new Random();

Console.WriteLine(random.Next());
Console.WriteLine(random2.Next());

Console.WriteLine(random.Next(1, 1000000));
Console.WriteLine(random2.Next(1, 1000000));

Console.WriteLine(random.Next(1, 100000));
Console.WriteLine(random2.Next(1, 100000));

Console.WriteLine(random.Next(1, 10000));
Console.WriteLine(random2.Next(1, 10000));


It is because Random's constructor uses current time to set up its seed value. This is something you need to keep in mind the next time you are working on creating random values.

Wednesday 29 May 2013

Procedure or function expects parameter which was not supplied : But its there.

This is a strange issue but a real one. One would normally assume that when executing a SQL server stored procedure, passing "null" as a value for a parameter which has data type as varchar/nvarchar is intuitive. However if you do it, you will get exception with a message like following:
 
"System.Data.SqlClient.SqlException: Procedure or function 'DoSomethingWithString' expects parameter '@inputString', which was not supplied."
 
Fix: It is actually pretty straightforward. Pass DBNull.Value instead of "null".
 
Here is the sample code that you can try.
 
Create a database named "Test" on local database server's default instance. Create a stored procedure in it using following script:
 
Create Procedure dbo.DoSomethingWithString
(
 @inputString NVARCHAR(256)
)
AS
BEGIN
 SET NOCOUNT ON
 SELECT @inputString AS 'Output'
END
 
Create a console application and add the following method:
 
 private static void TestNullStringParameter()
{
            string connectionString = "data source=(local);initial catalog=Test;integrated security=True;";
            try
            {
                using (IDbConnection conn = new SqlConnection(connectionString))
                {
                    using (IDbCommand command = conn.CreateCommand())
                    {
                        command.CommandText = "dbo.DoSomethingWithString";
                        command.CommandType = System.Data.CommandType.StoredProcedure;
                        //command.Parameters.Add(new SqlParameter("inputString", DBNull.Value));
                        command.Parameters.Add(new SqlParameter("inputString", null));
                        conn.Open();
                        using (IDataReader reader = command.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
                        {
                            if (reader.Read())
                            {
                                Console.WriteLine(reader[0]);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception!!");
                Console.WriteLine(e);
            }
}