ELENESSKI GAMES
  • Home
  • Games
    • Worzzler
    • The Lost Tribes
  • Unity
    • Facade Generator for Archimatix
    • Elenesski Object Database
    • Generic Move Camera
    • Unity C# Library
  • SQLINQ
    • Change Log
    • Concepts >
      • Overview
      • The Patterns
      • Database & Factories
      • Working with Tables
      • Custom Queries
      • Lazy Loading
      • Units of Work
    • Video Tutorials
    • Getting Started
    • Code Examples >
      • Implementing Behavior
      • Finding Objects
      • Custom Searches
      • Converters and Transformers
      • Object Association Management
      • New Objects
      • Creating Database
      • Associating Objects
      • Deleting Objects
      • Validating Objects
      • Saving
    • Sample Model >
      • Tutorial Model
      • Table Classes Code
      • Domain Classes Code
      • Factories Code
    • OSX Developers
    • Bridge Building
    • External Websites
    • Class Documentation
  • Presentations
    • 3D Ship Design
  • Music
    • Jamendo (Main)
    • Blend
    • Sound Cloud
    • Mixcloud (DJ)
    • DJ Demos
  • YouTube

implementing behavior

By default, the SQLINQ Generator is all about creating an ORM for the data attributes that make up your class.  But a proper object oriented system isn't concerned with the attributes, but rather the behaviour (aka logic) the class implements within it's methods.

All the classes the SQLINQ Generator are implemented with "partial".  This means you can extend the behaviour of those classes by simply duplicating the definition of them in another file.  Why another file?  Because the SQLINQ Generator is designed to be iterative.  You don't create a single class definition and are stuck with it throughout the evolution of your game.  You create what you need for the current game state, then evolve the class model as the game evolves.  For more information on this, see the SQLINQ Partial Classes section in SQLINQ Architecture Video (direct link).

This strategy means you cannot put your logic in the files that SQLINQ generates because they will be lost when the file is regenerated.  Therefore, you create duplicate files with the partial logic defined within them, and the C# linker will merge them together and have them appear as a single class.

To implement the behavioural extensions to the class you need 5 things:
  1. A new C# class file (.cs).  It can be called anything you want and stored anywhere within the Assets folder.  Of course, you want to create a logical name for it.  I strongly recommend against putting it in the same folder as the generated C# class.
  2. Your new class duplicates the same namespace.  Failing to do this will create two named classes in to different locations and the linker will not merge them because they are technically separate.
  3. Your new class uses the partial declaration.  The compiler/linker cannot work with definitions that are partial and non-partial.
  4. Your new class has the same name.  Without the same name, the linker cannot link the two definitions together.
  5. Your new class inherits from the same subclass or interface.  For domain objects, the class must inherit from "BaseClass" and table inherit/implement the "IBaseTable" interface.

​Example Domain


            namespace Assets.Data.DataDomain {
                public partial class District : BaseClass { ... }
            }

Example Table

            namespace Assets.Data.Tables {
                public partial class SettlementTable : IBaseTable { ... }
            }


Extending Factory?


Note: While Factory is also declared as partial, it's actually a static class.  While you can extend this class with additional features, our recommendation is to put those features in a different class, because a Factory is never instantiated.

​New 2018: If you are writing converters for your attributes, you place that logic into your own Partial Factory ...
New for 2018 Convertible Types: Prior to the change, your domain model could only have primitive types that were supported directly by the database.  In the new version, whenever the attribute uses the stereotype "convert", we generate a converter.  Your job is to convert the field into a string field so that it can be stored in the database, and provide a converter back from a string into the internal type. 

The converters are then placed into the partial static Factory that you create:

                namespace Assets.Data.Utility {
                    public static partial class Factory {

                        public static string ConvertVector2ToString(Vector2 aVector2) {
                            return aVector2.x + "," + aVector2.y;
                        }

                        public static Vector2 ConvertStringToVector2(string aString) {
                            string[] PARTS = aString.Split(",".ToCharArray());
                            return new Vector2(Convert.ToSingle(PARTS[0]), Convert.ToSingle(PARTS[1]));
                        }

                        public static string ConvertVector3ToString(Vector3 aVector3) {
                            return aVector3.x + "," + aVector3.y + "," + aVector3.z;
                        }

                        public static Vector3 ConvertStringToVector3(string aString) {
                            string[] PARTS = aString.Split(",".ToCharArray());
                            return new Vector3(Convert.ToSingle(PARTS[0])
                                                                   , Convert.ToSingle(PARTS[1])
                                                                   , Convert.ToSingle(PARTS[2]));
                        }

                        public static string ConvertQuaternionToString(Quaternion aQuaternion) {
                            return aQuaternion.x + "," + aQuaternion.y + "," + aQuaternion.z + "," + aQuaternion.w;
                        }

                        public static Quaternion ConvertStringToQuaternion(string aString) {
                            string[] PARTS = aString.Split(",".ToCharArray());
                            return new Quaternion( Convert.ToSingle(PARTS[0])
                                                                            , Convert.ToSingle(PARTS[1])
                                                                            , Convert.ToSingle(PARTS[2])
                                                                            , Convert.ToSingle(PARTS[3]) );
                        }

                    }
                }


The code shown above shows how to convert a Vector2, Vector3 and Quaternion to and from a string.  When the string is defined in the table, it's given an unlimited size, so any string up to 1Gb can be used.  This allows the class domain to reference the full type while saving the data as a string.  We also added "Using" tagged values so that the proper using statements are generated for the extra types you may want to define.