Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Database Driven Properties

4.71/5 (4 votes)
12 Nov 2014CPOL2 min read 14.4K   125  
Create a dynamic class driven by your database.

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.

C#
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 structs are placed into a dictionary that is keyed on the column names to write or read the data.

C#
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.

C#
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:

C#
private static SQLLiteDatabaseAdapter _sqlDatabase;

static void Main(string[] args)
{
    _sqlDatabase = new SQLLiteDatabaseAdapter
    (@"C:\DynamicClassExample\DynamicClassExample\Database\Test.db");
    
    // load content from TestContent table;
    var results = LoadContent("TestContent");
    
    foreach(var result in results)
    {
        int id = result.Properties.ValueOf("ID");
        
        Console.WriteLine(string.Format("Show ID = {0}", id));
    }
    
 // Lets see what we got from the database.
    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:

Image 1

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)