Monthly Archives: June 2011 - Page 2

Creating a zip file in .Net without using external libraries

I came across an article on Codeproject that show how to use the built-in Microsoft .Net 4 classes (hidden) to handle more generic zip files. .Net does have a public System.IO.Compression namespace but it only expose gzip class. There is also the System.IO.Packaging classes but it is proprietary interface to support only things like Office Open XML.

Fortunately the .Net 4 assembly WindowsBase.DLL contains some more generic zip file handling routines (MS.Internal.IO.Zip) but unfortunately it is not exposed publicly. With the use of reflection you can access it – although it is probably not recommended for general use as Microsoft can change the interfaces any time they like because it is not public. Also, because it uses reflection there might be a performance hit plus issues trying to use it while not running under Full Trust because it requires ‘ReflectionPermission’ permissions.

At least this is a potential alternative. On the long run it would be better if Microsoft expose a generic public zip file handling interface. There might be a licensing issue that is causing them not to include it – since the zip standard as far as I remember is owned by PKWARE and it is not public.

IlSpy

Until fairly recently you could use a free tool called Reflector to view/disassemble .Net libraries to see what is going on inside them. The company making this tool got greedy and is now charging for it – not nice of them. Fortunately another team of developers started creating another open source tool with similar functionality – IlSpy.

It also support plug-ins so it is also extendable. Nice!

Playing the Duke (Nukem)

I’m not doing a full review of the game – just making a few comments about it.

I played the demo a few days ago. It wasn’t terribly bad but recalling how much fun I had with the original Duke Nukem 3D game it just wasn’t as much fun. Now with the full game I can state that I can ‘up’ the opinion a little bit – but still not close to the original.

There are aspects of the game that is really good – well, at least compared to the original and perhaps to some other ‘recent’ games. The one thing that sets DNF apart from other recent games is the humor. They make no excuse for joking with other games – like Crysis and COD. Duke even sometimes make some funny comments about himself – in the 3rd person but that is what you would expect from a game like this.

One thing that feels a bit (ok… too much) overdone is the swearing. Yes, I know, the game is intended for a more mature audience but it is way too much and there is no way to ‘turn if off’ or replace with a ‘beep’. I can’t recall that there was much or any such swearing going on in the original.

Then there is the feeling that the game is a bit too much ‘scripted’ and you don’t really have a choice how you want to complete a level. Some levels aren’t really big so it creates the feeling that the game is a waste or too easy to play. Then there are sections where you run around in circles wondering what on earth you are suppose to do next. Usually the only indication that you are moving forward is that you keep on encountering more aliens to shoot. If they stop coming then you know you are done with the area.

Story wise, well… there isn’t much of one. Everything is pretty much what you would expect what would happen. Aliens come back, attack earth, steal the chicks, Duke gets mad and go kick butt. One aspect that might be a bit different is the ‘shrinking’ parts where Duke play, uhmm I mean fights while being ‘doll’ size. In the original there was something like this but only small sections. Now you play whole levels as mini Duke. It adds something even more humorous to the game – perhaps even silly.

Well, all in all I think the game is ‘ok’. Don’t go and expect this game to be a no 1 hit or something outa tis world. It really is just about the nostalgia and having a bit of almost mindless fun – much like Serious Sam.

Tweaking your SSD

Toms hardware has an article about ways to optimize both performance and capacity of your SSD drive. I have one at home and will definitely run through their check list to try and optimize the drive – for speed, capacity and lifespan.

http://www.tomshardware.com/reviews/ssd-performance-tweak,2911-16.html

Some optimizations work differently on different SSD drives – depending on how the manufacturer implemented their hardware. Some ‘optimizations actually can make things worse so be sure to compare things before and after the change before you just accept it. Some optimizations might even be a bit controversial like the disabling of the paging file. It really depends on what you’re willing to sacrifice to reach a level of performance you can live with.

Duke Nukem not so fornever

Well, apparent the almost impossible has happened. For years it was black listed as just vaporware but now finally after years of waiting my copy of DNF is on its way.

I played the demo and was just semi impressed – actually, the only part that really impressed is that it was released at all and playable but… lets not beat down the king while he’s rising! You don’t play a game like this because it is better than other games – rather because it is a classic.

Now only the courier company must put some speed inside their delivery vans!

Soon it should be time to chew a$$ and kick bubblegum!

 

[Update: so the courier made it – perhaps he was chased by an pig alien… hehe]

Downside of democracy

The following is just a thought… or two about this subject.

In principle democracy is a good thing but what happens if the majority of people are idiots that don’t know or care about the greater good? You end up with with a bigger mess than any non-democratic system can create…

Xml file as a database – part 4

Today’s part will be a slight deviation from what I planned last time. I got side-tracked with trying to save the xml file in a compressed format and actually managed to achieve it.

DotNetZip library

Thanks to this open source library it is possible to output the xml generated by the DataSet straight to a zip file – it is not necessary to first save the xml file and then zip it. To achieve this all you need is the following:

private void WriteToZipFile(string zipFilePath, DataSet ds)
{

MemoryStream mStream = new MemoryStream();
ds.WriteXml(mStream, XmlWriteMode.WriteSchema);
mStream.Seek(0, SeekOrigin.Begin);

if (File.Exists(zipFilePath))

File.Delete(zipFilePath);

using (ZipFile zipFile = new ZipFile(zipFilePath))
{

zipFile.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
zipFile.AddEntry(ds.DataSetName + “.xml”, mStream);
zipFile.Save();

}

}

private Stream ReadFromZipFile(string zipFilePath, string dsName)
{

MemoryStream mStream = new MemoryStream();
using (ZipFile zipFile = new ZipFile(zipFilePath))
{

if ((from z in zipFile.Entries
where z.FileName == dsName + “.xml”
select z).Count() > 0)
{

ZipEntry ze = (from z in zipFile.Entries
where z.FileName == dsName + “.xml”
select z).First();

ze.Extract(mStream);
mStream.Seek(0, SeekOrigin.Begin);

}

}

return mStream;

}

Using it is as simple as this:

DatabaseTest dbt = new DatabaseTest(); // Typed DataSet
…
//Saving
WriteToZipFile(“SomeFileName.zip”, dbt);

//Loading
DatabaseTest dbt2 = new DatabaseTest();
dbt2.ReadXml(ReadFromZipFile(“SomeFileName.zip”, dbt.DataSetName), XmlReadMode.IgnoreSchema); //Important to ‘exclude’ the schema for a typed DataSet

Really simple hey? Since xml is very ‘compressionable’ (like most text files) you can save quite a bit on disk space.

Find a copy of it here.

WriteToZipFile(saveFileDialogXml.FileName + ".zip", dbt);

Xml file as a database – part 3

Last time I stopped with the sample code how to produce a DataSet in code and then save and load it from a file. This time I’ll just continue with the ‘typed’ DataSet version plus show what the output would look like. Interestingly, the output of both the untyped and typed versions looks (essentially) the same.

First I’ll show how the Typed DataSet version works. Just to refresh the old minds – to create a Typed DataSet you use Visual Studio’s new template for a DataSet xsd and then use the designer to add tables, columns and relationships. Then in code you can do the following (the DataSet is named ‘DatabaseTest’):

DatabaseTest dbt = new DatabaseTest();
DatabaseTest.SurnameRow surname = (DatabaseTest.SurnameRow)dbt.Surname.NewRow();
surname.Surname = “Henning”;
surname.TS = DateTime.Now;
dbt.Surname.AddSurnameRow(surname);
surname = (DatabaseTest.SurnameRow)dbt.Surname.NewRow();
surname.Surname = “Van Der Merwe”;
surname.TS = DateTime.Now;
dbt.Surname.AddSurnameRow(surname);

DatabaseTest.PersonRow pa = (DatabaseTest.PersonRow)dbt.Person.NewRow();
pa.FirstName = “Daddy Koos”;
pa.SurnameId = 1;
pa.TS = DateTime.Now;
pa.YearOfBirth = 1945;
dbt.Person.AddPersonRow(pa);

DatabaseTest.PersonRow ma = (DatabaseTest.PersonRow)dbt.Person.NewRow();
ma.FirstName = “Mommy Johanna”;
ma.SurnameId = 2;
ma.TS = DateTime.Now;
ma.YearOfBirth = 1950;
dbt.Person.AddPersonRow(ma);

DatabaseTest.PersonRow guy = (DatabaseTest.PersonRow)dbt.Person.NewRow();
guy.FirstName = “Little Koos”;
guy.SurnameId = 1;
guy.TS = DateTime.Now;
guy.YearOfBirth = 1971;
guy.FatherID = 1;
guy.MotherID = 2;
guy.ChildNo = 1;
dbt.Person.AddPersonRow(guy);

if (saveFileDialogXml.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{

if (System.IO.File.Exists(saveFileDialogXml.FileName))

System.IO.File.Delete(saveFileDialogXml.FileName);

dbt.WriteXml(saveFileDialogXml.FileName, XmlWriteMode.WriteSchema);

var people = (from p in dbt.Person
join s in dbt.Surname on p.SurnameId equals s.Id
select new
{

PersonId = p.Id,
FirstName = p.FirstName,
Surname = s.Surname

});
StringBuilder sb = new StringBuilder();
foreach (var p in people)
{

sb.AppendLine(string.Format(“{0} {1}”, p.FirstName, p.Surname));

}
MessageBox.Show(sb.ToString());

System.Diagnostics.Process pro = new System.Diagnostics.Process();
pro.StartInfo = new System.Diagnostics.ProcessStartInfo(System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.System), “notepad.exe”));
pro.StartInfo.Arguments = “\”” + saveFileDialogXml.FileName + “\””;
pro.Start();

}

This provides the same functionality as before. The output looks something like this (sorry, I’m a bit lazy to format/indend the output too much now):

<?xml version=”1.0″ standalone=”yes”?>
<DatabaseTest xmlns=”http://tempuri.org/DatabaseTest.xsd”>
<xs:schema id=”DatabaseTest” targetNamespace=”http://tempuri.org/DatabaseTest.xsd” xmlns:mstns=”http://tempuri.org/DatabaseTest.xsd” xmlns=”http://tempuri.org/DatabaseTest.xsd” xmlns:xs=”http://www.w3.org/2001/XMLSchema” xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata” attributeFormDefault=”qualified” elementFormDefault=”qualified”>
<xs:element name=”DatabaseTest” msdata:IsDataSet=”true” msdata:UseCurrentLocale=”true”>
<xs:complexType>
<xs:choice minOccurs=”0″ maxOccurs=”unbounded”>
<xs:element name=”Person“>
<xs:complexType>
<xs:sequence>
<xs:element name=”Id” msdata:AutoIncrement=”true” msdata:AutoIncrementSeed=”1″ type=”xs:int” />
<xs:element name=”FirstName” type=”xs:string” />
<xs:element name=”SurnameId” type=”xs:int” />
<xs:element name=”Description” type=”xs:string” minOccurs=”0″ />
<xs:element name=”YearOfBirth” type=”xs:int” minOccurs=”0″ />
<xs:element name=”MonthOfBirth” type=”xs:unsignedByte” minOccurs=”0″ />
<xs:element name=”DayOfBirth” type=”xs:unsignedByte” minOccurs=”0″ />
<xs:element name=”TS” type=”xs:dateTime” />
<xs:element name=”FatherID” type=”xs:int” minOccurs=”0″ />
<xs:element name=”MotherID” type=”xs:int” minOccurs=”0″ />
<xs:element name=”PlaceOfBirthId” type=”xs:int” minOccurs=”0″ />
<xs:element name=”YearOfDeath” type=”xs:int” minOccurs=”0″ />
<xs:element name=”MonthOfDeath” type=”xs:unsignedByte” minOccurs=”0″ />
<xs:element name=”DayOfDeath” type=”xs:unsignedByte” minOccurs=”0″ />
<xs:element name=”PlaceOfDeathId” type=”xs:int” minOccurs=”0″ />
<xs:element name=”GenealogicalNo” type=”xs:string” minOccurs=”0″ />
<xs:element name=”ChildNo” type=”xs:unsignedByte” default=”0″ minOccurs=”0″ />
<xs:element name=”ProgenitorCode” type=”xs:string” minOccurs=”0″ />
<xs:element name=”IsProgenitor” type=”xs:boolean” minOccurs=”0″ />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name=”Surname“>
<xs:complexType>
<xs:sequence>
<xs:element name=”Id” msdata:AutoIncrement=”true” msdata:AutoIncrementSeed=”1″ type=”xs:int” />
<xs:element name=”Surname” type=”xs:string” />
<xs:element name=”TS” type=”xs:dateTime” />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name=”Place“>
<xs:complexType>
<xs:sequence>
<xs:element name=”Id” msdata:AutoIncrement=”true” msdata:AutoIncrementSeed=”1″ type=”xs:int” />
<xs:element name=”Place” type=”xs:string” />
<xs:element name=”TS” type=”xs:dateTime” />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name=”Marriage“>
<xs:complexType>
<xs:sequence>
<xs:element name=”Id” msdata:AutoIncrement=”true” msdata:AutoIncrementSeed=”1″ type=”xs:int” />
<xs:element name=”No” type=”xs:unsignedByte” default=”0″ minOccurs=”0″ />
<xs:element name=”HusbandId” type=”xs:int” />
<xs:element name=”WifeId” type=”xs:int” />
<xs:element name=”YearOfMarriage” type=”xs:int” minOccurs=”0″ />
<xs:element name=”MonthOfMarriage” type=”xs:unsignedByte” minOccurs=”0″ />
<xs:element name=”DayOfMarriage” type=”xs:unsignedByte” minOccurs=”0″ />
<xs:element name=”PlaceOfMarriageId” type=”xs:int” minOccurs=”0″ />
<xs:element name=”YearOfDivorce” type=”xs:int” minOccurs=”0″ />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name=”Constraint1″ msdata:PrimaryKey=”true”>
<xs:selector xpath=”.//mstns:Person” />
<xs:field xpath=”mstns:Id” />
</xs:unique>
<xs:unique name=”Surname_Constraint1″ msdata:ConstraintName=”Constraint1″ msdata:PrimaryKey=”true”>
<xs:selector xpath=”.//mstns:Surname” />
<xs:field xpath=”mstns:Id” />
</xs:unique>
<xs:unique name=”Constraint2″>
<xs:selector xpath=”.//mstns:Surname” />
<xs:field xpath=”mstns:Surname” />
</xs:unique>
<xs:unique name=”Place_Constraint1″ msdata:ConstraintName=”Constraint1″ msdata:PrimaryKey=”true”>
<xs:selector xpath=”.//mstns:Place” />
<xs:field xpath=”mstns:Id” />
</xs:unique>
<xs:unique name=”Place_Constraint2″ msdata:ConstraintName=”Constraint2″>
<xs:selector xpath=”.//mstns:Place” />
<xs:field xpath=”mstns:Place” />
</xs:unique>
<xs:unique name=”Marriage_Constraint1″ msdata:ConstraintName=”Constraint1″ msdata:PrimaryKey=”true”>
<xs:selector xpath=”.//mstns:Marriage” />
<xs:field xpath=”mstns:Id” />
</xs:unique>
<xs:keyref name=”FK_Person_Marriage” refer=”Constraint1″>
<xs:selector xpath=”.//mstns:Marriage” />
<xs:field xpath=”mstns:HusbandId” />
</xs:keyref>
<xs:keyref name=”FK_Person_Marriage1″ refer=”Constraint1″>
<xs:selector xpath=”.//mstns:Marriage” />
<xs:field xpath=”mstns:WifeId” />
</xs:keyref>
<xs:keyref name=”FK_Person_Person1″ refer=”Constraint1″>
<xs:selector xpath=”.//mstns:Person” />
<xs:field xpath=”mstns:MotherID” />
</xs:keyref>
<xs:keyref name=”FK_Person_Surname” refer=”Surname_Constraint1″>
<xs:selector xpath=”.//mstns:Person” />
<xs:field xpath=”mstns:SurnameId” />
</xs:keyref>
<xs:keyref name=”FK_Place_Person” refer=”Place_Constraint1″>
<xs:selector xpath=”.//mstns:Person” />
<xs:field xpath=”mstns:PlaceOfBirthId” />
</xs:keyref>
<xs:keyref name=”FK_Person_Person” refer=”Constraint1″>
<xs:selector xpath=”.//mstns:Person” />
<xs:field xpath=”mstns:FatherID” />
</xs:keyref>
</xs:element>
</xs:schema>

<Person>
<Id>1</Id>
<FirstName>Daddy Koos</FirstName>
<SurnameId>1</SurnameId>
<YearOfBirth>1945</YearOfBirth>
<TS>2011-06-06T09:15:58.0021555+02:00</TS>
<ChildNo>0</ChildNo>
</Person>
<Person>
<Id>2</Id>
<FirstName>Mamma Johanna</FirstName>
<SurnameId>2</SurnameId>
<YearOfBirth>1950</YearOfBirth>
<TS>2011-06-06T09:52:51.4151521+02:00</TS>
<ChildNo>0</ChildNo>
</Person>
<Person>
<Id>3</Id>
<FirstName>Little Koos</FirstName>
<SurnameId>1</SurnameId>
<YearOfBirth>1971</YearOfBirth>
<TS>2011-06-06T09:52:51.4151521+02:00</TS>
<FatherID>1</FatherID>
<MotherID>2</MotherID>
<ChildNo>1</ChildNo>
</Person>

<Surname>
<Id>1</Id>
<Surname>Henning</Surname>
<TS>2011-06-06T09:15:57.9771555+02:00</TS>
</Surname>
<Surname>
<Id>2</Id>
<Surname>Van Der Merwe</Surname>
<TS>2011-06-06T09:52:51.4121521+02:00</TS>
</Surname>

</DatabaseTest>

As you can see the xsd is actually embedded inside the xml file. This is helpful to see the structure of the data.

Next step

The next step is to create a Data Access Layer because dealing with a DataSet directly in code is so… old fashioned… and so on. Stay tuned for the next iteration.

Xml file as a database part 2

Been a but busy lately but I didn’t give up on the idea of an xml database yet. Actually, I started with some code even before the first post – that is in principle working but it still needs a lot of work. Unfortunately I’ve been side-tracked on other things in the last couple of days so the whole idea is just sitting idle for the moment.

First let me cover some (old) basics. The following examples are nothing new and functionality available for quite a number of years using plain old DataSets.

The first concept is how to create define or create a DataSet in code or run-time. Look at the following example:

DataSet myDb = new DataSet(“XmlDb”);
DataTable personTable = new DataTable(“Person”);

DataColumn personId = new DataColumn(“Id”, typeof(int)) { AutoIncrement = true, AutoIncrementSeed = 1, Unique = true, AllowDBNull = false };
DataColumn surnameId = new DataColumn(“Id”, typeof(int)) { AutoIncrement = true, AutoIncrementSeed = 1, Unique = true, AllowDBNull = false };
DataColumn personSurnameId = new DataColumn(“SurnameId”, typeof(int)) { AllowDBNull = false };
DataColumn fatherId = new DataColumn(“FatherID”, typeof(int));
DataColumn motherId = new DataColumn(“MotherID”, typeof(int));

personTable.Columns.AddRange(new DataColumn[]
{

personId,
new DataColumn(“Name”, typeof(string)) { AllowDBNull = false},
personSurnameId,
new DataColumn(“YearOfBirth”, typeof(int)),
new DataColumn(“MonthOfBirth”, typeof(int)),
new DataColumn(“DayOfBirth”, typeof(int)),
new DataColumn(“Description”, typeof(string)),
fatherId,
motherId

});
personTable.PrimaryKey = new DataColumn[] { personId };
myDb.Tables.Add(personTable);

DataTable surnameTable = new DataTable(“Surname”);
surnameTable.Columns.AddRange(new DataColumn[]
{

surnameId,
new DataColumn(“Surname”, typeof(string)) { Unique=true, AllowDBNull=false }

});
surnameTable.PrimaryKey = new DataColumn[] { surnameId };
myDb.Tables.Add(surnameTable);
DataRelation personSurname = new DataRelation(“PersonSurname”, surnameId, personSurnameId);
myDb.Relations.Add(personSurname);
DataRelation personFather = new DataRelation(“PersonFather”, personId, fatherId);
myDb.Relations.Add(personFather);
DataRelation personMother = new DataRelation(“PersonMother”, personId, motherId);
myDb.Relations.Add(personMother);

The piece of code above shows a couple of things (which probably includes bad programming habits as well… but it is only an example 😉 ). First it creates a DataSet with two tables. The two tables have a relationship between them that will enforce some referential integrity. Both tables have an id field that is an autonumber/identity column. The ‘Person’ table also adds two internal references (parent-child relationship). No rocket science here (yet).

The next block demonstrates how to add raw data to the DataSet.

DataRow newSurname = surnameTable.NewRow();
newSurname[“Surname”] = “Van Der Merwe”;
surnameTable.Rows.Add(newSurname);

newSurname = surnameTable.NewRow();
newSurname[“Surname”] = “Botha”;
surnameTable.Rows.Add(newSurname);

DataRow newRow = personTable.NewRow();
newRow[“Name”] = “Piet”;
newRow[“SurnameId”] = 1;
newRow[“Description”] = “Testing 123”;
personTable.Rows.Add(newRow);

newRow = personTable.NewRow();
newRow[“Name”] = “Sannie”;
newRow[“SurnameId”] = 2;
newRow[“YearOfBirth”] = 1950;
personTable.Rows.Add(newRow);

newRow = personTable.NewRow();
newRow[“Name”] = “Koos”;
newRow[“SurnameId”] = 1;
newRow[“YearOfBirth”] = 1980;
newRow[“FatherID”] = 1;
newRow[“MotherID”] = 2;
personTable.Rows.Add(newRow);

Again, no rocket science here. Two surnames are added and then 3 people. The third person reference the first two (parents).

Then if you want  to ‘persist’ the DataSet:

if (saveFileDialogXml.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{

if (System.IO.File.Exists(saveFileDialogXml.FileName))

System.IO.File.Delete(saveFileDialogXml.FileName);

myDb.WriteXml(saveFileDialogXml.FileName, XmlWriteMode.WriteSchema);

…

Then lastly you might want to reload it back into another DataSet to add some more data etc.

DataSet myDb2 = new DataSet();
myDb2.ReadXml(saveFileDialogXml.FileName);

personTable = myDb2.Tables[“Person”];
newRow = personTable.NewRow();
newRow[“Name”] = “Gert”;
newRow[“SurnameId”] = 1;
personTable.Rows.Add(newRow);

So there you have the basics how a simple .Net DataSet can be used to create, load, persist, reload and change data to and from an Xml file. Personally I’d like to add another step to compress (zip) the data while on disk – to make it easier to transport if needed. This will not impact functionality or performance of the running application.

One concern is of course what happens when the ‘database’ grows big because if you haven’t noticed, the entire database must be loaded/saved when you interact with the Xml file. This concept will not allow you to use extremely large databases – but then it is not intended for mission critical enterprise database systems! On the positive side – the database is ‘in memory’ so it should be very fast. Splitting the file and loading only sections will make it very tricky and possibly mean you have to wrote a lot of custom code.

It is also possible to use a Typed DataSet in exactly the same manner. The advantage then is you don’t have to define the ‘database structure’ in code. The rest works basically the same.