Tuesday, July 29, 2008

Runing CRD 8.2.2 against SQL Server 2005 Express


There are some particular considerations when install CRD 8.2.2 against SQL Server 2005 Express:

(1) SQL Server 2005 Express must installed as default instance. No other instance should ever be installed.
(2) Installation works on XP SP2.
(3) Must create TM_DEV user in login first before restore data.bak. And server role should be empty, especially should not have "public" role visible.
(4) Must use SQL Configuration manager to enable Client VIA, TCP/IP, ShareMemeory, NamedPipes.
(5) Create a new Database CRD822 and install into it with "Overwrite Existing DB" option checked.
(6) TM_DEV mapping to PDF_User dbo_owner roles. ( start up server while doing CRD client installation).

Sunday, July 13, 2008

LINQ to Text file through StreamReader Extension method


Text file data feeds come in different format but with common theme: parse a line into an object representation. Here is one example of the object:

public class BrokerDataItem : ILineParser<BrokerDataItem>
{
public string Ticker { get; set;}
public double Price { get; set;}
public long QTY { get; set;}
public string Trader { get; set;}
public DateTime TradeDate { get; set;}
public string TradeType { get; set;}

public BrokerDataItem() { }
public BrokerDataItem Parse(string[] p)
{
return null;
}
public BrokerDataItem Parse(string entireLine) {
string[] p = entireLine.Split(',');
Ticker = p[0].ToString();
Price = Convert.ToDouble(p[1]);
QTY = Convert.ToInt64(p[2]);
Trader = p[3].ToString();
TradeDate = Convert.ToDateTime(p[4]);
TradeType = p[5].ToString();
return this;
}

Note I abstracted parse operation into interface

public interface ILineParser<T>
{
T Parse(string[] p);
T Parse(string entireLine);
}

So that I can create an Extension Method for StreamReader that return the Data Object to LINQ. Consequently, this allows LINQ runs against data object of any source to get the required data elements:

public static class AnyThing
{
public static IEnumerable<T> GetData<T>(this StreamReader sr) where T : ILineParser<T>, new()
{
string L;
while ((L = sr.ReadLine()) != null)
{
T t = new T();
yield return t.Parse(L);
}
}
}


class Program
{
static void Main(string[] args)
{
StreamReader sr = new StreamReader(@"..\..\Data.txt");

var t =
from data in sr.GetData<BrokerDataItem>()
select data;
foreach (BrokerDataItem i in t)
Console.WriteLine(i.Ticker+" " + i.Price.ToString());
Console.ReadLine();
}
}

Here are the data:
FBN U8,134.79, 1000,JIMMYD,7/14/2008,BUYL
FBN U8,444.90, 7832,JIMMYD,7/14/2008,BUYL
FBN U8,4567.9, 1000,JIMMYD,7/14/2008,SELL
FBN U8,581.79, 5634,JIMMYD,7/14/2008,BUYL
FBN U8,724.78, 1212,JIMMYD,7/14/2008,SELL
FBN U8,932.01, 8892,JIMMYD,7/14/2008,SELL
FBN U8,678.88, 3,JIMMYD,7/14/2008,BUYL

Finally, extension method is not required since you can just create an IEnumerable and use it in LINQ.

Friday, July 11, 2008

Data Proection API

DPAPI uses the key from the following location to encrypt/decrypt:

C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto
or

C:\WINDOWS\system32\Microsoft\Protect or Crypto.

These are replaced by SID if DataProtectionScope.LocalMachine is replaced by DataProtectionScope.CurrentUser.
In theory, if data are moved away from the machine, there would no way to decrypt,
even DataProtectionScope.CurrentUser for the same user logged on to a different machine:


byte[] entropyBytes =null;// Encoding.Unicode.GetBytes("GMO");
byte[] pBytes;
private void button1_Click(object sender, EventArgs e)
{
string plainText = this.textBox1.Text;
byte[] plainBytes = Encoding.Unicode.GetBytes(plainText);

pBytes = ProtectedData.Protect(plainBytes, entropyBytes, DataProtectionScope.LocalMachine);
string ps = Convert.ToBase64String(pBytes);
this.textBox2.Text = ps;

}

private void button2_Click(object sender, EventArgs e)
{
byte[] upBytes = ProtectedData.Unprotect(pBytes, entropyBytes, DataProtectionScope.LocalMachine);
this.textBox3.Text = Encoding.Unicode.GetString(upBytes);
}