Tuesday, 28 October 2008

SQL: Basic Transact-SQL commands and syntax

This article is not suppose to make you become a Transact-SQL export, instead it is only suppose to make me don't look like a idiot when reading a SQL Stored Procedure. In that perspective I wrote this article which covered some basic but very often used SQL syntax and command.

1st of all, how to declare variables. The followed code declared a integer, a string and a record-set point:

DECLARE @Counter int
DECLARE @RegionName NVARCHAR(510)
DECLARE @RegionId TABLE (RegionId int)


2nd of al, let’s take a look how to create code block, a classic sample will be like this:

BEGIN TRY 
  BEGIN TRAN
    IF NOT EXIST (SELECT ...) –- make your condition here
    BEGIN
      -- do your stuff here 
    END
  COMMIT
END TRY
BEGIN CATCH
  IF @@Trancount >0
    ROLLBACK

  DECLARE @err VARCHAR(500)
  SET @err = ERROR_MESSAGE()
  RAISERROR (@err, 16, 1)
END CATCH

GO

Above is a complete cycle when you are trying to do some database operation with Transaction cooperation. We begin a TRY block first (if there is error the CATCH block will catch it), and inside the TRY block we can do anything we want, in this case, typically we put a IF BEGIN END block here. In the CATCH block we first try to ROLLBACK all the changes we made first by check the @@Trancount value to see if there is any Transaction started, and then we raise a error message out.

3rd of all, what does the GO sentence do? GO is not a Transact-SQL statement, it just simply signals the end of a batch of Transact-SQL statements. No any Transact-SQL statement can occupy the same line as a GO command but the comments.

In another word, GO marked a end of a T-SQL batch, after the GO any variable will be brand new and unknown. Here is a example from MSDN:

USE pubs
GO

DECLARE @MyMsg VARCHAR(50)
SELECT @MyMsg = 'Hello, World.'
GO
-- @MyMsg is not valid after this GO ends the batch.

-- Yields an error because @MyMsg not declared in this batch.
PRINT @MyMsg
GO


4th of all, a good stuff, SET IDENTITY_INSERT. Allows explicit values to be inserted into the identity column of a table. As you know after you set the table identity field to auto increasing integer you can insert a record with a particular id value any more. But by swtich on/off the IDENTITY_INSERT you can do it.

SET IDENTITY_INSERT MyTable ON
  -- Insert records with any id value you want
SET IDENTITY_INSERT MyTable OFF


5th of all, create and delete a table in T-SQL:

-- Create products table.
CREATE TABLE products (id int IDENTITY PRIMARY KEY, product varchar(40))
GO

-- Drop products table.
DROP TABLE products
GO 


6th of all, some useful methods you can use in your SQL:

* ISNULL ( check_expression , replacement_value ) , Replaces NULL with the specified replacement value.
* COALESCE ( expression [ ,...n ] ) , Returns the first non null expression among its arguments.
* GETDATE, Returns the current system date and time in the SQL Server standard internal format for date-time values.



Then followed is a example to show you how to change current existed table's structure.

If NOT EXISTS ( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='HighlightBox'
                and COLUMN_NAME='EndPrice' )
BEGIN
  ALTER TABLE HighlightBox ADD EndPrice decimal(10,2) NULL
  ALTER TABLE HighlightBox WITH CHECK ADD CONSTRAINT FK_HighlightBox_TicketAvailabilityID
        FOREIGN KEY(TicketAvailabilityID)
        REFERENCES Ticket_Availability (Ticket_Availability_Id)
END
GO


Finally, there are some rules from MSDN apply to T-SQL batches:

* CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE TRIGGER, and CREATE VIEW statements cannot be combined with other statements in a batch. The CREATE statement must begin the batch. All other statements that follow in that batch will be interpreted as part of the definition of the first CREATE statement.

* A table cannot be altered and then the new columns referenced in the same batch.

* If an EXECUTE statement is the first statement in a batch, the EXECUTE keyword is not required. The EXECUTE keyword is required if the EXECUTE statement is not the first statement in the batch. Security Note Batch files may contain credentials stored in plain text. Credentials may be echoed to the user's screen during batch execution.

Tuesday, 21 October 2008

C#: Decimal type vs. Float and Double types

Have you ever wondered what is the difference between the .NET "decimal" data type and the similar "float" or "double" data types? Ever wonder when you should use one instead of other? This article is going to help you and myself to work these questions out.

First of all, take a look at the following C# code:

var f = 1.1f;
var dbl = 1.1;
var d = 1.1m;

Response.Write((f + 0.1f).ToString("e20"));
Response.Write("<br />");
Response.Write((dbl + 0.1).ToString("e20"));
Response.Write("<br />"); Response.Write((d + 0.1m).ToString("e20"));

Note: when you declare a float variable like float f = 1.1 you will receive a build error says type 'double' cannot be implicitly converted to type 'float'; use an 'F' suffix to create a literal of this type, which means any decimal without suffix will be created as a double type.

Now here is what the ouptput looks like:

1.20000005000000000000e+000
1.20000000000000020000e+000
1.20000000000000000000e+000

You can see the three results are all slightly different. Why is this? Also, why was 1.20000005 instead of the hard-coded 1.20000000? The reason is simple - we’re working on hardware that uses binary floating point representation as opposed to decimal representation. Binary floating point is really an approximation of the true decimal number because it is base two (binary) instead of base 10 (decimal).

The Decimal Type, instead, is simply a floating point type that is represented internally as base 10 instead of base two. Obviously with base 10 (our real-world numbering system) any decimal number can be constructed to the exact value without approximating. :) The Decimal type is really  really a software implementation of base 10 arithmetic.

Which Type Should I Use?

Since Decimal types are perfectly accurate and float’s are not, why would we still want to use the intrinsic float/double types? Short answer - performance. In my speed tests Decimal types ran over 20 times slower than their float counterparts.

So if you’re writing a financial application for a bank that has to be 100% accurate and performance is not a consideration, use the Decimal type. On the other hand, if you need performance and extremely small floating point variations don’t affect your program, stick with the float and double types.

Other Considerations

Another thing the Decimal type can do that the float and double types cannot is encode trailing zero’s. For example, there is a difference between 7.5 and 7.50 in the decimal type, but there is no way to represent this in a standard float/double. Let’s look at another example:

double dbl = 1.23 + 1.27;
Response.Write(string.Format("double: {0}", dbl));
Response.Write("<br />");
decimal d = 1.23m + 1.27m;
Response.Write(string.Format("decimal: {0}", d));

This output looks like this:

double: 2.5
decimal: 2.50

The first part that uses a double outputs 2.5, but the second one that uses a decimal outputs 2.50 - we didn’t even have to specify a format string in order to get that trailing zero. This could be very useful in applications that deal with dollar amounts.

Thursday, 16 October 2008

ASP.NET Error: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).

There is a chance sometimes you can get this HttpException: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>). Just like itself mentioned, if you check your aspx page you must can find some <% ... %> exception inside. There are two ways to fix it.

Option 1: move the code into any runat="server" tag, which means move the code into a server side html tag. The tag could be <head runat="server"></head>, or <form runat="server"></form>.

If you can’t put the code into any server side tag (it is wired if this happen :-) ) then there is Option 2:
Step 1: override the OnInit(), like this:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    Page.DataBind(); // Add this new line.
}

Then step 2, in your code replace all the <% … %> or <%= … %> to <%# … %>. Done. I will do more research and probably can tell you what actually happened very soon. -- The End

Tuesday, 14 October 2008

JavaScript: JavaScript Better Practices

There are some tips to make your JavaScript code runing faster.
  • Use "var" whenever a variable is to be declared
  • Reduce scopes (Try avoiding nesting functions or loops)
  • Avoid string concatenation, use Array instead - “push” each pieces of the string into array and then use “join” to get the complete string
  • Use less DOM element concatenation - concatenate everything into string/Array first, then assign to the DOM element
  • Introduce function delegate. This one is worth mentioning. When calling a function in a loop, delegate before the loop because JavaScript interpreter will use the function then as local variable and will not lookup in its scope chain for the function body in each iteration. Code:
    var delegate = myFunc; // myFunc is the function
    delegate(el1);
  • Introduct DOM elements and function caching. Similar to function delegation. Example:
    var divContentAppendChild = document.getElementById("div1").appendChild;

    for (var i = 0; i < count; i++)
        divContentAppendChild(element[i]);
  • Avoid using switch if possible, as JavaScript interpreter can’t optimize switch block.
The End. :)

The .NET Framework type to ADO.NET data type mappings

.NET Framework Type ADO.NET Database Type SQL Data Type
String Varchar Varchar()
String Nvarchar Nvarchar()
String NChar Nchar()
String NText NText
String Text Text
Double BigInt Float
DateTime DateTime Datetime
DateTime SmallDateTime Smalldatetime
Int Int Int
Int64 BigInt Bigint
Int16 SmallInt smallint
Byte[] Binary Binary()
Byte[] Image Image
Byte[] VarBinary Varbinary()
Byte TinyInt Tinyint
Bool Bit Bit
Decimal Decimal Decimal
Decimal Money Money
Decimal SmallMoney SmallMoney
Float Float Float
Guid UniqueIdentifier Uniqueidentifier
Real Real Real

Monday, 13 October 2008

ASP.NET MVC: First shoot, the ActionResult type

When I created my first MVC project I noticed this method named Index which is created automatically by MVC framework.

public ActionResult Index()
{
    // Add action logic here
    return View();
}

When you move mouse over the View() method you will see it returns a instance of ViewResult type but not a ActionResult type. The ViewResult type is actually inherited indirectly from ActionResult type. The complete inheritance structure is:

ActionResult
|
|--PartialViewResult
|
|----ViewResult

The whole story here is we created a Index action for current Controller which means when you just go to this website and don’t specify any page name you will go into this Index action. What this action does is initialize the page view and return a ViewResult object for MVC viewer to use.