/// <summary> /// Saves all instances to the database /// </summary> public void Save() { foreach (SEntity entity in this.Instances.Values) { Type t = entity.GetType(); IList <FieldInfo> fields = SEntity.GetFieldsOrdered(t); if (entity.Existing) { //...update attributes... } else { // create new StringBuilder sb = new StringBuilder(); sb.Append("INSERT INTO "); sb.Append(t.Name); sb.Append("(oid"); foreach (FieldInfo f in fields) { if (!f.FieldType.IsGenericType) // don't deal with lists { sb.Append(", "); sb.Append(f.Name); } } sb.Append(") VALUES ("); sb.Append(entity.OID.ToString()); foreach (FieldInfo f in fields) { if (!f.FieldType.IsGenericType) // don't deal with lists { sb.Append(", "); object val = f.GetValue(entity); if (val is SEntity) { SEntity entref = (SEntity)val; sb.Append(entref.OID); } else if (val is byte[]) { byte[] bval = (byte[])val; sb.Append("'"); sb.Append(BitConverter.ToString(bval)); sb.Append("'"); } else if (val != null) { string encoded = val.ToString(); if (encoded != null) { if (val is string || val is Enum) { sb.Append("'"); } sb.Append(encoded.Replace("'", "''")); // escape single quotes - note: does not handle other unicode quotes if (val is string || val is Enum) { sb.Append("'"); } } else { sb.Append("NULL"); } } else { sb.Append("NULL"); } } } sb.Append(");"); Execute(sb.ToString()); entity.Existing = true; } // lists foreach (FieldInfo f in fields) { if (f.FieldType.IsGenericType) { string tablename = t.Name + "_" + f.Name; // clear existing Execute("DELETE FROM " + tablename + " WHERE source=" + entity.OID.ToString() + ";"); System.Collections.IList list = (System.Collections.IList)f.GetValue(entity); if (list != null) { for (int i = 0; i < list.Count; i++) { SEntity target = (SEntity)list[i]; Execute("INSERT INTO " + tablename + " (source, sequence, target) VALUES (" + entity.OID.ToString() + ", " + i.ToString() + ", " + target.OID.ToString() + ");"); } } } } } }
/// <summary> /// Creates database table(s) for type /// </summary> /// <param name="t"></param> public void InitType(Type t) { StringBuilder sb = new StringBuilder(); sb.Append("CREATE TABLE "); sb.Append(t.Name); sb.Append(" (oid INTEGER"); IList <FieldInfo> fields = SEntity.GetFieldsOrdered(t); foreach (FieldInfo f in fields) { if (!f.FieldType.IsGenericType) // don't deal with lists { sb.Append(", "); sb.Append(f.Name); sb.Append(" "); if (typeof(SEntity).IsAssignableFrom(f.FieldType)) { sb.Append(" INTEGER"); // oid } else if (f.FieldType.IsEnum) { sb.Append(" VARCHAR"); } else if (typeof(string) == f.FieldType) { //if (f.Name.Equals("_Documentation") || f.Name.Equals("_Description") || f.Name.Equals("_Expression")) if (f.Name.Equals("_Name")) { // for name, indexable sb.Append(" VARCHAR"); } else { // all others unlimited text sb.Append(" TEXT"); } } else if (typeof(bool) == f.FieldType) { sb.Append(" BIT"); } else if (typeof(int) == f.FieldType) { sb.Append(" INTEGER"); } else if (typeof(double) == f.FieldType) { sb.Append(" FLOAT"); } else if (typeof(byte[]) == f.FieldType) { sb.Append(" TEXT"); } else { System.Diagnostics.Debug.WriteLine("FormatMDB::InitType() - incompatible field type"); } } } sb.Append(");"); Execute(sb.ToString()); // populate relationships for LISTs foreach (FieldInfo f in fields) { if (f.FieldType.IsGenericType && f.FieldType.GetGenericTypeDefinition() == typeof(List <>)) { sb = new StringBuilder(); sb.Append("CREATE TABLE "); sb.Append(t.Name); sb.Append("_"); sb.Append(f.Name); sb.Append(" (source INTEGER, sequence INTEGER, target INTEGER);"); Execute(sb.ToString()); } } }
/// <summary> /// Loads all instances from the database /// </summary> public void Load() { // first pass: load all entities and non-list attributes foreach (Type t in this.m_typemap.Values) { StringBuilder sb = new StringBuilder(); sb.Append("SELECT * FROM "); sb.Append(t.Name); IList <FieldInfo> fields = SEntity.GetFieldsOrdered(t); // load scalar attributes using (OleDbCommand cmd = this.m_connection.CreateCommand()) { cmd.CommandText = sb.ToString(); using (OleDbDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { int oid = reader.GetInt32(0); SEntity entity = null; if (!this.Instances.TryGetValue(oid, out entity)) { entity = (SEntity)System.Runtime.Serialization.FormatterServices.GetUninitializedObject(t); entity.Existing = true; entity.OID = oid; this.Instances.Add(entity.OID, entity); if (entity.OID > m_lastOID) { this.m_lastOID = entity.OID; } } int index = 0; foreach (FieldInfo f in fields) { if (!f.FieldType.IsGenericType) { // non-list attribute index++; object value = reader.GetValue(index); if (value != null && !(value is DBNull)) { if (f.FieldType.IsEnum) { object eval = Enum.Parse(f.FieldType, value.ToString()); f.SetValue(entity, eval); } else if (typeof(SEntity).IsAssignableFrom(f.FieldType)) { if (value is Int32) { int ival = (int)value; SEntity eval = null; if (this.Instances.TryGetValue(ival, out eval)) { f.SetValue(entity, eval); } } } else if (typeof(byte[]) == f.FieldType) { string strval = (string)value; int len = strval.Length / 2; Byte[] valuevector = new byte[len]; for (int i = 0; i < len; i++) { char hi = strval[i * 2 + 0]; char lo = strval[i * 2 + 1]; byte val = (byte)( ((hi >= 'A' ? +(int)(hi - 'A' + 10) : (int)(hi - '0')) << 4) + ((lo >= 'A' ? +(int)(lo - 'A' + 10) : (int)(lo - '0')))); valuevector[i] = val; } f.SetValue(entity, valuevector); } else { f.SetValue(entity, value); } } } } } } } } // second pass: load lists (now that all entities are loaded) foreach (Type t in this.m_typemap.Values) { StringBuilder sb = new StringBuilder(); sb.Append("SELECT * FROM "); sb.Append(t.Name); sb.Append(";"); IList <FieldInfo> fields = SEntity.GetFieldsOrdered(t); // load vector attributes using (OleDbCommand cmd = this.m_connection.CreateCommand()) { cmd.CommandText = sb.ToString(); using (OleDbDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { long oid = (long)reader.GetInt32(0); SEntity entity = this.Instances[oid]; foreach (FieldInfo f in fields) { if (f.FieldType.IsGenericType) { // list System.Collections.IList list = (System.Collections.IList)f.GetValue(entity); if (list == null) { list = (System.Collections.IList)Activator.CreateInstance(f.FieldType); f.SetValue(entity, list); } using (OleDbCommand cmdList = this.m_connection.CreateCommand()) { StringBuilder sbl = new StringBuilder(); sbl.Append("SELECT * FROM "); sbl.Append(t.Name); sbl.Append("_"); sbl.Append(f.Name); sbl.Append(" WHERE source="); sbl.Append(entity.OID.ToString()); sbl.Append(" ORDER BY sequence;"); cmdList.CommandText = sbl.ToString(); using (OleDbDataReader readerList = cmdList.ExecuteReader()) { while (readerList.Read()) { long refid = (long)readerList.GetInt32(2); SEntity target = this.Instances[refid]; list.Add(target); } } } } } } } } } }
private void WriteEntity(SEntity o) { // sanity check if (this.m_indent > 100) { return; } Type t = o.GetType(); string hyperlink = "../../schema/" + t.Namespace.ToLower() + "/lexical/" + t.Name.ToLower() + ".htm"; this.WriteStartElement(t.Name, hyperlink); #if false // id if (gen != null) { bool firstTime; long id = gen.GetId(o, out firstTime); writer.WriteAttributeString("id", "i" + id.ToString()); } #endif /* * writer.WriteStartAttribute("id"); * writer.WriteValue("i" + id.ToString()); * writer.WriteEndAttribute();*/ // write fields as attributes bool haselements = false; IList <FieldInfo> fields = SEntity.GetFieldsOrdered(t); foreach (FieldInfo f in fields) { object v = f.GetValue(o); if (v != null) { if (f.FieldType.IsValueType) { Type ft = f.FieldType; if (ft.IsGenericType && ft.GetGenericTypeDefinition() == typeof(Nullable <>)) { // special case for Nullable types ft = ft.GetGenericArguments()[0]; } Type typewrap = null; while (ft.IsValueType && !ft.IsPrimitive) { FieldInfo fieldValue = ft.GetField("Value"); if (fieldValue != null) { v = fieldValue.GetValue(v); if (typewrap == null) { typewrap = ft; } ft = fieldValue.FieldType; } else { break; } } if (v != null) { string encodedvalue = System.Security.SecurityElement.Escape(v.ToString()); m_writer.Write(" "); m_writer.Write(f.Name); m_writer.Write("=\""); m_writer.Write(encodedvalue); //... escape it m_writer.Write("\""); } } else { haselements = true; } } } IList <FieldInfo> inverses = SEntity.GetFieldsInverse(t); if (haselements || inverses.Count > 0) { WriteOpenElement(); // write direct object references and lists foreach (FieldInfo f in fields) { DocXsdFormat format = GetXsdFormat(f); // hide fields where inverse attribute used instead if (!f.FieldType.IsValueType && (format == null || (format.XsdFormat != DocXsdFormatEnum.Hidden))) { WriteAttribute(o, f); } } // write inverse object references and lists foreach (FieldInfo f in inverses) { DocXsdFormat format = GetXsdFormat(f); if (format != null && format.XsdFormat == DocXsdFormatEnum.Element) //... check this { WriteAttribute(o, f); //... careful - don't write back-references... } } WriteEndElement(t.Name); } else { // close opening tag if (this.m_markup) { this.m_writer.WriteLine("/><br/>"); } else { this.m_writer.WriteLine("/>"); } this.m_indent--; } }