http://msdn.microsoft.com/en-us/library/ff647793.aspx
http://www.sqlservercentral.com/stairway/72399/ - indexes
Allow Multipel Processors to be involved in running your stored procedure:
- OPTION (MAXDOP 8)
If you're given a task to be done in TDD, it's not usually whether you can resolve that problem. It's about testing whether you have the right mindset, process and coding style that TDD suggests:
a good sample for OUTER APPLY:
Returning the latest record of a child table:
SELECT ST.[SystemDetailID], ST.[SystemName], LH.LatestLoadStatus
FROM [SystemTable] AS ST
LEFT OUTER JOIN
(
SELECT LHInner.LoadStatus AS LatestLoadStatus, LHInner.SystemDetailID FROM [dbo].[LoadHistory] AS LHInner
WHERE LHInner.LoadHistoryID in
(
SELECT LatestLoadHisotoryID FROM
(
SELECT MAX(LoadHistoryID) as LatestLoadHisotoryID, SystemDetailID FROM [dbo].[LoadHistory]
GROUP BY SystemDetailID
) l
)
) AS LH ON ST.SystemDetailID = LH.SystemDetailID
A simpler/shorter approach is:
SELECT ST.[SystemDetailID],
ST.[SystemName],
LH.LatestLoadStatus
FROM [SystemTable] AS ST
OUTER APPLY (SELECT TOP 1 *
FROM [dbo].[LoadHistory] LH
WHERE ST.SystemDetailID = LH.SystemDetailID
ORDER BY LoadHistoryID DESC) LH
More info: http://technet.microsoft.com/en-us/library/ms175156.aspx
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace MyProject
{
public interface IEncryptionManager
{
string Encrypt(string originalText);
string Decrypt(string encryptedText);
}
/// <summary>
/// This class uses the Rijndael Encryption Algorithm
/// </summary>
public class RijndaelEncryptionManager : IEncryptionManager
{
#region Fields
/// <summary>
/// The key can only be 16, 24 or 32 bytes.
/// </summary>
private static readonly byte[] EncryptionKey = new byte[] { 0x00, 0x11, 0x22, 0x03, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xC0, 0xDD, 0x0E, 0xFF };
/// <summary>
/// The vector also can only be 16, 24 or 32 bytes.
/// </summary>
private static readonly byte[] InitializationVector = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0xFD, 0x0E, 0x0F};
#endregion
#region Methods
public string Encrypt(string originalText)
{
using (var myRijndael = new RijndaelManaged { Key = EncryptionKey, IV = InitializationVector })
{
// Encrypt the string to an array of bytes.
var encryptedBytes = EncryptStringToBytes(originalText, myRijndael.Key, myRijndael.IV);
return Convert.ToBase64String(encryptedBytes);
}
}
public string Decrypt(string encryptedText)
{
using (var myRijndael = new RijndaelManaged { Key = EncryptionKey, IV = InitializationVector })
{
// Encrypt the string to an array of bytes.
var encryptedBytes = Convert.FromBase64String(encryptedText);
// Decrypt the bytes to a string.
return DecryptStringFromBytes(encryptedBytes, myRijndael.Key, myRijndael.IV);
}
}
/// <summary>
/// Encrypts the string to bytes.
/// </summary>
/// <param name="plainText">The plain text.</param>
/// <param name="key">The key.</param>
/// <param name="iv">The IV.</param>
/// <returns></returns>
static byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] iv)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (key == null || key.Length <= 0)
throw new ArgumentNullException("key");
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException("key");
byte[] encrypted;
// Create an Rijndael object
// with the specified key and IV.
using (var rijAlg = Rijndael.Create())
{
rijAlg.Key = key;
rijAlg.IV = iv;
// Create a decrytor to perform the stream transform.
var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
/// <summary>
/// Decrypts the string from bytes.
/// </summary>
/// <param name="cipherText">The cipher text.</param>
/// <param name="key">The key.</param>
/// <param name="iv">The IV.</param>
/// <returns></returns>
static string DecryptStringFromBytes(byte[] cipherText, byte[] key, byte[] iv)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (key == null || key.Length <= 0)
throw new ArgumentNullException("key");
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException("key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Rijndael object
// with the specified key and IV.
using (var rijAlg = Rijndael.Create())
{
rijAlg.Key = key;
rijAlg.IV = iv;
// Create a decrytor to perform the stream transform.
var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
#endregion
}
}
Background:
There are times when we’d like to remove duplicated codes in instantiating types so we use generics to group similar classes and work with them easier.
Look at these classes:
public abstract class BaseType
{
protected int A { get; set; }
protected int B { get; set; }
protected BaseType(int a, int b)
{
this.A = a;
this.B = b;
}
}
public class Type1 : BaseType
{
public Type1(int a, int b) : base(a, b)
{
}
}
public class Type2 : BaseType
{
public Type2(int a, int b) : base(a, b)
{
}
}
TypeCreator<T>(int a, int b) where T : BaseType
{
// instantiate type with a and b
}
Now I show you different ways to implement this.
1) Using Activator.CreateInstance… – anti-pattern
The simplest way to implement this would be to use the Activator.CreateInstance method. There are numerous articles which says this approach has an awful performance and avoid it but I’d just like to show how it simply works:public static class MyTypeFactory<T> where T : BaseType
{
public static T Create(int a, int b)
{
return (T)Activator.CreateInstance(typeof(T), a, b);
}
}
// and use it like this
MyTypeFactory<Type1>.Create(1, 2);
{
static MyTypeFactory()
{
MethodRunner<Type1>.Func = (a, b) => new Type1(a, b);
MethodRunner<Type2>.Func = (a, b) => new Type2(a, b);
}
public static T Create<T>(int a, int b) where T: BaseType
{
return MethodRunner<T>.Func(a, b);
}
static class MethodRunner<T>
{
public static Func<int, int, T> Func { get; set; }
}
}
The static constructor of the MyTypeFactory class only runs once per application domain the first time the factory is accessed so it should also be thread-safe.
You can simply use it like this:
var type1 = MyTypeFactory.Create<Type1>(1, 2);
3) Using Expression Trees
In this approach, a lambda expression has to be compiled per type. So for each type a new compilation will be done initially then they're stored in a private field for further reuse. This has much better performance in comparison with Activator.CreateInstance.
Another good point about this approach is its flexibility; you don’t have to hard code the constructors like approach 2.
public static class MyTypeFactory<T> where T : BaseType
{
private static readonly Func<int, int, T> MethodDelegate = InitializeMethodDelegate();
private static Func<int, int, T> InitializeMethodDelegate()
{
var constructorInfo = typeof(T).GetConstructor(new[] { typeof(int), typeof(int) });
var param1 = Expression.Parameter(typeof(int));
var param2 = Expression.Parameter(typeof(int));
return Expression.Lambda<Func<int, int, T>>(Expression.New(constructorInfo, param1, param2), param1, param2).Compile();
}
public static T Create(int a, int b)
{
return MethodDelegate(a, b);
}
}
Purpose:
When an item is selected from the drop down list, a method on the server should be called. AutoPostBack = True can’t be used as posting back the whole page is not required.
Page Source:
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
<script language="javascript" type="text/javascript">
$(document).ready(function () {
var selector = ".ddlCountries";
$(selector ).change(function () {
PageMethods.OnSelectedIndexChanged($(selector).val());
});
});
script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" EnablePartialRendering="true">
</asp:ScriptManager>
<asp:DropDownList CssClass="ddlCountries" ID="ddlCountries" runat="server" Width="100px">
</asp:DropDownList>
</asp:Content>
protected void Page_Load(object sender, EventArgs e)
{
BindDummyData();
}
private void BindDummyData()
{
var countries = new [] {new { Name = "UK", ID = "1" },
new { Name = "USA", ID = "2" }
};
foreach (var country in countries)
{
this.ddlCountries.Items.Add(new ListItem(country.Name, country.ID));
}
}
[WebMethod]
public static void OnSelectedIndexChanged(string selectedValue)
{
// process
}