using System; using System.Collections.Generic; using System.Linq; using System.Text; using FLocal.Core; using FLocal.Core.DB; namespace FLocal.Common { abstract public class SqlObject : Core.DataObject where T : SqlObject, new() where TKey : struct { protected SqlObject() : base() { } abstract protected ISqlObjectTableSpec table { get; } private bool _isLoaded = false; protected bool isLoaded { get { return this._isLoaded; } private set { this._isLoaded = value; } } private object lockFiller = new object(); private object lockInitializer = new object(); abstract protected void doFromHash(Dictionary data); /// /// Note that this method does not updates isLoaded field! /// /// private void fromHash(Dictionary data) { lock(this.lockFiller) { if(data[this.table.idName] != this.id.ToString()) { throw new CriticalException("Id mismatch"); } this.doFromHash(data); } } /// /// Note that this method does not updates isLoaded field! /// /// private void doLoad() { this.fromHash(Config.instance.mainConnection.LoadById(this.table, this.id.ToString())); } private void Load() { lock(this.lockInitializer) { if(this.isLoaded) throw new CriticalException("already initialized"); this.doLoad(); this.isLoaded = true; } } protected void LoadFromHash(Dictionary data) { lock(this.lockInitializer) { if(this.isLoaded) throw new CriticalException("already initialized"); this.fromHash(data); this.isLoaded = true; } } protected void LoadIfNotLoaded() { if(!this.isLoaded) { lock(this.lockInitializer) { if(!this.isLoaded) { this.doLoad(); this.isLoaded = true; } } } } public void ReLoad() { lock(this.lockInitializer) { this.doLoad(); this.isLoaded = true; } } protected override void AfterCreate(bool forLoadingFromHash) { base.AfterCreate(forLoadingFromHash); if(!forLoadingFromHash) this.Load(); } protected static void Refresh(TKey id) { Dictionary objects = LoadByIdsForLoadingFromHash(new List() { id }); objects[id].ReLoad(); } } abstract public class SqlObject : SqlObject, IComparable where T : SqlObject, new() { public static List LoadByIds(IEnumerable ids) { Dictionary rawRes = LoadByIdsForLoadingFromHash(ids); List idsToQuery = new List(); foreach(int id in ids) { if(!rawRes[id].isLoaded) { idsToQuery.Add(id); } } List loadedIds = new List(); if(idsToQuery.Count > 0) { ITableSpec table = rawRes[idsToQuery[0]].table; List> rawData = Config.instance.mainConnection.LoadByIds(table, new List(from int id in idsToQuery select id.ToString())); foreach(Dictionary row in rawData) { int id = int.Parse(row[table.idName]); loadedIds.Add(id); if(!rawRes.ContainsKey(id)) throw new CriticalException("wrong id"); rawRes[id].LoadFromHash(row); } } List res = new List(); foreach(int id in ids) { if(!rawRes[id].isLoaded) { throw new CriticalException("#" + id + " not loaded (all ids (" + ids.ToPrintableString() + "), idsToQuery (" + idsToQuery.ToPrintableString() + "), loaded ids (" + loadedIds.ToPrintableString() + ")"); } res.Add(rawRes[id]); } return res; } int IComparable.CompareTo(T other) { if(other.id > this.id) { return -1; } else if(other.id == this.id) { return 0; } else { return 1; } } } }