An alternative to UBB.threads
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FLocal/Common/SqlObject.cs

167 lines
4.3 KiB

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<TKey, T> : Core.DataObject<TKey, T>
where T : SqlObject<TKey, T>, new()
where TKey : struct {
protected SqlObject() : base() {
}
abstract protected ISqlObjectTableSpec table {
get;
}
private volatile bool _isLoaded = false;
protected bool isLoaded {
get {
return this._isLoaded;
}
private set {
this._isLoaded = value;
}
}
private volatile object lockFiller = new object();
private volatile object lockInitializer = new object();
abstract protected void doFromHash(Dictionary<string, string> data);
/// <summary>
/// Note that this method does not updates isLoaded field!
/// </summary>
/// <param name="data"></param>
private void fromHash(Dictionary<string, string> data) {
lock(this.lockFiller) {
if(data[this.table.idName] != this.id.ToString()) {
throw new CriticalException("Id mismatch");
}
this.doFromHash(data);
}
}
/// <summary>
/// Note that this method does not updates isLoaded field!
/// </summary>
/// <param name="data"></param>
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<string, string> data) {
lock(this.lockInitializer) {
if(this.isLoaded) throw new CriticalException("already initialized");
this.fromHash(data);
this.isLoaded = true;
}
}
protected void LoadFromHashIfNotLoaded(Dictionary<string, string> data) {
lock(this.lockInitializer) {
if(this.isLoaded) return;
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.LoadIfNotLoaded();
}*/
protected static void Refresh(TKey id) {
Dictionary<TKey, T> objects = LoadByIdsForLoadingFromHash(new List<TKey>() { id });
objects[id].ReLoad();
}
}
abstract public class SqlObject<T> : SqlObject<int, T>, IComparable<T> where T : SqlObject<T>, new() {
public static List<T> LoadByIds(IEnumerable<int> ids) {
Dictionary<int, T> rawRes = LoadByIdsForLoadingFromHash(ids);
List<int> idsToQuery = new List<int>();
foreach(int id in ids) {
if(!rawRes[id].isLoaded) {
idsToQuery.Add(id);
}
}
List<int> loadedIds = new List<int>();
if(idsToQuery.Count > 0) {
ITableSpec table = rawRes[idsToQuery[0]].table;
List<Dictionary<string, string>> rawData = Config.instance.mainConnection.LoadByIds(table, new List<string>(from int id in idsToQuery select id.ToString()));
foreach(Dictionary<string, string> row in rawData) {
int id = int.Parse(row[table.idName]);
loadedIds.Add(id);
if(!rawRes.ContainsKey(id)) throw new CriticalException("wrong id");
rawRes[id].LoadFromHashIfNotLoaded(row);
}
}
List<T> res = new List<T>();
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<T>.CompareTo(T other) {
if(other.id > this.id) {
return -1;
} else if(other.id == this.id) {
return 0;
} else {
return 1;
}
}
internal actions.UpdateChange GetUpdateChange(Dictionary<string, actions.AbstractFieldValue> data) {
return new actions.UpdateChange(
this.table,
data,
this.id
);
}
}
}