Opinions on code.

03/17/2013 12:46 12k#1
Just curious on some opinions on this DB system im kind of laying out. Haven't tested nor implemented this yet, just want some ideas if u will. My thoughts is that this will prevent having to create indexes etc in SQL, yet still making it so your server doesnt have to sort through a massive item list.

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Database
{
    public class Database
    {
        private string DBPath = "";
        public Database(string AccountName)
        {
            this.DBPath = "Accounts/" + AccountName;
            if (!Directory.Exists(this.DBPath))
            {
                Directory.CreateDirectory(this.DBPath);
                Directory.CreateDirectory(this.DBPath + "/Items");
                Directory.CreateDirectory(this.DBPath + "/Friends");
                Directory.CreateDirectory(this.DBPath + "/Enemies");
                Directory.CreateDirectory(this.DBPath + "/Logs");
                Directory.CreateDirectory(this.DBPath + "/Skills");
                Directory.CreateDirectory(this.DBPath + "/Profs");
            }
        }
        public IDictionary<uint, ConquerItem> LoadItems()
        {
            IDictionary<uint, ConquerItem> Items = new Dictionary<uint, ConquerItem>();
            foreach (string FileName in Directory.GetFiles(this.DBPath + "/Items"))
            {
                uint ItemUID;
                if (uint.TryParse(FileName, out ItemUID))
                {
                    BinaryReader BR = new BinaryReader(new FileStream(this.DBPath + "/Items/" + FileName, FileMode.Open));
                    ConquerItem Item = new ConquerItem();
                    Item.UID = ItemUID;
                    Item.ItemID = BR.ReadUInt32(); //0-4
                    Item.Durability = BR.ReadUInt16(); //4-6
                    Item.Position = BR.ReadByte(); //6-7
                    Item.SocketOne = BR.ReadByte(); //7-8
                    Item.SocketTwo = BR.ReadByte(); //8-9
                    Item.Plus = BR.ReadByte(); //9-10
                    Item.Bless = BR.ReadByte(); //10-11
                    Item.Locked = BR.ReadByte(); //11-12
                    Item.Enchant = BR.ReadByte(); //12-13
                    Item.Color = BR.ReadByte(); //13-14
                    Item.ExtraAttribute = BR.ReadByte(); //14-15
                    int OwnerLen = BR.ReadByte(); //15-16
                    Item.Owner = ASCIIEncoding.ASCII.GetString(BR.ReadBytes(OwnerLen)); //16-32 max (16 digit account length)
                    BR.BaseStream.Close();
                    BR.Close();
                }
            }
            return Items;
        }
        public void AddItem(ConquerItem Item)
        {
            BinaryWriter BW = new BinaryWriter(new FileStream(this.DBPath + "/Items/" + Item.UID, FileMode.Create));
            BW.Write(Item.UID);
            BW.Write(Item.ItemID);
            BW.Write(Item.Durability);
            BW.Write(Item.Position);
            BW.Write(Item.SocketOne);
            BW.Write(Item.SocketTwo);
            BW.Write(Item.Plus);
            BW.Write(Item.Bless);
            BW.Write(Item.Locked);
            BW.Write(Item.Enchant);
            BW.Write(Item.Color);
            BW.Write(Item.ExtraAttribute);
            BW.Write((byte)Item.Owner.Length);
            BW.Write(Item.Owner);
            BW.BaseStream.Close();
            BW.Close();
        }
        public void UpdateItem(uint ItemUID, Enums.ItemUpdateType UpdateType, uint Value)
        {
            BinaryWriter BW = new BinaryWriter(new FileStream(this.DBPath + "/Items/" + ItemUID, FileMode.Open));
            byte Position = 0;
            switch (UpdateType)
            {
                case Enums.ItemUpdateType.UID:
                case Enums.ItemUpdateType.Owner:
                    {
                        BW.BaseStream.Close();
                        BW.Close();
                        return;
                    }
                case Enums.ItemUpdateType.ID: Position = 0; break;
                case Enums.ItemUpdateType.Durability: Position = 4; break;
                case Enums.ItemUpdateType.Position: Position = 6; break;
                case Enums.ItemUpdateType.SocketOne: Position = 7; break;
                case Enums.ItemUpdateType.SocketTwo: Position = 8; break;
                case Enums.ItemUpdateType.Plus: Position = 9; break;
                case Enums.ItemUpdateType.Bless: Position = 10; break;
                case Enums.ItemUpdateType.Locked: Position = 11; break;
                case Enums.ItemUpdateType.Enchant: Position = 12; break;
                case Enums.ItemUpdateType.Color: Position = 13; break;
                case Enums.ItemUpdateType.ExtraAttribute: Position = 14; break;
                default: break;
            }
            BW.Seek(Position, SeekOrigin.Begin);
            BW.Write(Value);
            BW.BaseStream.Close();
            BW.Close();
        }
        public void UpdateItem(uint ItemUID, Enums.ItemUpdateType UpdateType, ushort Value)
        {
            BinaryWriter BW = new BinaryWriter(new FileStream(this.DBPath + "/Items/" + ItemUID, FileMode.Open));
            byte Position = 0;
            switch (UpdateType)
            {
                case Enums.ItemUpdateType.UID:
                case Enums.ItemUpdateType.Owner:
                    {
                        BW.BaseStream.Close();
                        BW.Close();
                        return;
                    }
                case Enums.ItemUpdateType.ID: Position = 0; break;
                case Enums.ItemUpdateType.Durability: Position = 4; break;
                case Enums.ItemUpdateType.Position: Position = 6; break;
                case Enums.ItemUpdateType.SocketOne: Position = 7; break;
                case Enums.ItemUpdateType.SocketTwo: Position = 8; break;
                case Enums.ItemUpdateType.Plus: Position = 9; break;
                case Enums.ItemUpdateType.Bless: Position = 10; break;
                case Enums.ItemUpdateType.Locked: Position = 11; break;
                case Enums.ItemUpdateType.Enchant: Position = 12; break;
                case Enums.ItemUpdateType.Color: Position = 13; break;
                case Enums.ItemUpdateType.ExtraAttribute: Position = 14; break;
                default: break;
            }
            BW.Seek(Position, SeekOrigin.Begin);
            BW.Write(Value);
            BW.BaseStream.Close();
            BW.Close();
        }
        public void UpdateItem(uint ItemUID, Enums.ItemUpdateType UpdateType, byte Value)
        {
            BinaryWriter BW = new BinaryWriter(new FileStream(this.DBPath + "/Items/" + ItemUID, FileMode.Open));
            byte Position = 0;
            switch (UpdateType)
            {
                case Enums.ItemUpdateType.UID:
                case Enums.ItemUpdateType.Owner:
                    {
                        BW.BaseStream.Close();
                        BW.Close();
                        return;
                    }
                case Enums.ItemUpdateType.ID: Position = 0; break;
                case Enums.ItemUpdateType.Durability: Position = 4; break;
                case Enums.ItemUpdateType.Position: Position = 6; break;
                case Enums.ItemUpdateType.SocketOne: Position = 7; break;
                case Enums.ItemUpdateType.SocketTwo: Position = 8; break;
                case Enums.ItemUpdateType.Plus: Position = 9; break;
                case Enums.ItemUpdateType.Bless: Position = 10; break;
                case Enums.ItemUpdateType.Locked: Position = 11; break;
                case Enums.ItemUpdateType.Enchant: Position = 12; break;
                case Enums.ItemUpdateType.Color: Position = 13; break;
                case Enums.ItemUpdateType.ExtraAttribute: Position = 14; break;
                default: break;
            }
            BW.Seek(Position, SeekOrigin.Begin);
            BW.Write(Value);
            BW.BaseStream.Close();
            BW.Close();
        }
        public void UpdateItem(uint ItemUID, Enums.ItemUpdateType UpdateType, string Value)
        {
            BinaryWriter BW = new BinaryWriter(new FileStream(this.DBPath + "/Items/" + ItemUID, FileMode.Open));
            BW.Seek(15, SeekOrigin.Begin);
            BW.Write((byte)Value.Length);
            BW.Write(Value);
            BW.BaseStream.Close();
            BW.Close();
        }
        public void RemoveItem(uint ItemUID)
        {
            File.Delete(this.DBPath + "/Items/" + ItemUID);
        }
        public IList<string> LoadFriends()
        {
            IList<string> Friends = new List<string>();
            foreach (string FileName in Directory.GetFiles(this.DBPath + "/Friends"))
                Friends.Add(FileName);
            return Friends;
        }
        public void AddFriend(string FriendName)
        {
            File.Create(this.DBPath + "/Friends/" + FriendName);
        }
        public void RemoveFriend(string FriendName)
        {
            File.Delete(this.DBPath + "/Friends/" + FriendName);
        }
        public IList<string> LoadEnemies()
        {
            IList<string> Enemies = new List<string>();
            foreach (string FileName in Directory.GetFiles(this.DBPath + "/Enemies"))
                Enemies.Add(FileName);
            return Enemies;
        }
        public void AddEnemy(string EnemyName)
        {
            File.Create(this.DBPath + "/Enemies/" + EnemyName);
        }
        public void RemoveEnemy(string EnemyName)
        {
            File.Delete(this.DBPath + "/Enemies/" + EnemyName);
        }
        public IDictionary<ushort, byte> LoadSkills()
        {
            IDictionary<ushort, byte> Skills = new Dictionary<ushort, byte>();
            foreach (string FileName in Directory.GetFiles(this.DBPath + "/Skills"))
            {
                ushort SkillID;
                if (ushort.TryParse(FileName, out SkillID))
                {
                    BinaryReader BR = new BinaryReader(new FileStream(this.DBPath + "/Skills/" + FileName, FileMode.Open));
                    Skills.Add(SkillID, BR.ReadByte());
                    BR.BaseStream.Close();
                    BR.Close();
                }
            }
            return Skills;
        }
        public void AddSkill(ushort SkillID, byte Level)
        {
            BinaryWriter BW = new BinaryWriter(new FileStream(this.DBPath + "/Skills/" + SkillID, FileMode.Create));
            BW.Write(Level);
            BW.BaseStream.Close();
            BW.Close();
        }
        public void RemoveSkill(ushort SkillID)
        {
            File.Delete(this.DBPath + "/Skills/" + SkillID);
        }
        public IDictionary<ushort, byte> LoadProfs()
        {
            IDictionary<ushort, byte> Profs = new Dictionary<ushort, byte>();
            foreach (string FileName in Directory.GetFiles(this.DBPath + "/Profs"))
            {
                ushort ProfID;
                if (ushort.TryParse(FileName, out ProfID))
                {
                    BinaryReader BR = new BinaryReader(new FileStream(this.DBPath + "/Profs/" + FileName, FileMode.Open));
                    Profs.Add(ProfID, BR.ReadByte());
                    BR.BaseStream.Close();
                    BR.Close();
                }
            }
            return Profs;
        }
        public void AddProf(ushort ProfID, byte Level)
        {
            BinaryWriter BW = new BinaryWriter(new FileStream(this.DBPath + "/Profs/" + ProfID, FileMode.Create));
            BW.Write(Level);
            BW.BaseStream.Close();
            BW.Close();
        }
        public void RemoveProf(ushort ProfID)
        {
            File.Delete(this.DBPath + "/Profs/" + ProfID);
        }
    }
}
03/17/2013 19:14 Korvacs#2
SQL makes this redundant, it wont scale.
03/17/2013 21:34 pro4never#3
^

Flatfile systems (no matter how you implement it outside of essentially writing your own relational database software) do not scale as you add more and more entries/tables/columns and rule out using incredibly powerful tools such as sql syntax to retreive data.


I think Korv has argued over this a number of times and it all boils down to why re-invent the wheel? Database systems were created to make up for the shortcomings of flat file databases. As such any flatfile database system you might create will almost certainly fall short of any public database system out there and if you're willing to put enough work into it to make it a competitive alternative then... that's its own (rather advanced) project and not something to be considered as part of something like a pserver project.


TL: DR - use a database system if you need scaleability (large number of entries that are interconnected) and use flatfile if you need relatively static data dumps that don't need to be heavily processed or retrieved/edited constantly.