Introduction
I am a novice game developer and wanted an easy method of loading and saving game content. I didn't necessarily want to use the entity framework type setup, so I came up with a design that suited my needs for this project. I found it to be very useful and decided to share, hopefully others find it somewhat useful as well.
Background
The code in this example has a dependency on the .NET 4.0 x86 SQL Lite (http://system.data.sqlite.org/downloads/1.0.94.0/sqlite-netFx40-setup-bundle-x86-2010-1.0.94.0.exe) in addition to which I also used SQL Lite Browser (http://sqlitebrowser.org/) which is completely optional. I found it useful for creating and editing the database.
Using the Code
For my specific project, I decomposed my data types into an integer and a string
, these are the basic building blocks to use in the application. Using this information, I created a structure that could be used as a integer or a string
. Each Property
is created from a column in the database table and the data portion is from the row which is represented by the "Value
" or "Text
" depending on the data type specific in the database table.
public struct Property
{
public int? Value;
public string Text;
public Type Type;
public Property(Type type, object data)
{
this.Text = string.Empty;
Value = null;
Type = type;
if (type.Equals(typeof(string)))
{
Text = data.ToString();
}
else
{
int tmpValue = 0;
if (int.TryParse(data.ToString(), out tmpValue))
{
Value = tmpValue;
}
}
}
}
I came up with a collection to store these properties. Each of the Property struct
s are placed into a dictionary
that is keyed on the column names to write or read the data.
private Dictionary<string, Property> _properties;
public PropertyContainer(DataRow row, DataColumnCollection columns)
{
_properties = new Dictionary<string, Property>(columns.Count);
foreach (DataColumn column in columns)
{
_properties.Add(column.ColumnName, new Property(column.DataType, row[column.ColumnName]));
}
}
I then added some helper methods to pull / push data to the properties in the container.
public int ValueOf(string key)
{
lock (_lockRead)
{
if (_properties.ContainsKey(key) == true)
{
return _properties[key].Value.Value;
}
else
{
Console.WriteLine(string.Format("No property with the key = {0} found.", key));
}
return int.MinValue;
}
}
public void SetValueOf(string key, int value)
{
lock (_lockWrite)
{
if (_properties.ContainsKey(key) == true)
{
Property property = _properties[key];
property.Value = value;
_properties[key] = property;
}
else
{
Console.WriteLine(string.Format("No property with the key = {0} found.", key));
}
}
}
Similar methods are in the source for text as well.
I am attaching the source with the example database and the following code on how to load and access the data.
Usage is as given below:
private static SQLLiteDatabaseAdapter _sqlDatabase;
static void Main(string[] args)
{
_sqlDatabase = new SQLLiteDatabaseAdapter
(@"C:\DynamicClassExample\DynamicClassExample\Database\Test.db");
var results = LoadContent("TestContent");
foreach(var result in results)
{
int id = result.Properties.ValueOf("ID");
Console.WriteLine(string.Format("Show ID = {0}", id));
}
foreach (var result in results)
{
Console.WriteLine("*Record*");
foreach (var property in result.Properties.Properties)
{
if (property.Value.Type == typeof(string))
{
Console.WriteLine(string.Format("Type = {0}, Key = {1} ,
Value = {2}", property.Value.Type, property.Key, property.Value.Text));
}
else
{
Console.WriteLine(string.Format("Type = {0}, Key = {1} ,
Value = {2}", property.Value.Type, property.Key, property.Value.Value.Value));
}
}
Console.WriteLine("------------------");
}
Console.ReadLine();
}
The output is as follows:
Things to Consider
I have not done any extensive performance testing on this as of yet, this may be a consideration in not using this type of setup.
Also, I am sure there are ways that this can be made more generic in the property class, I am sure someone more intelligent than myself can point that out. :)
I have tried this approach with a Microsoft Access database as well, I would imagine this design would work for any database in concept.
History
This is the baseline of this design.