public void AddField(string fieldName, System.Data.DbType fieldType, int length, bool isPrimaryKey, bool requireUnique, FieldOrder searchOrder) { if (this.Registered & !this.AllowRuntimeChanges) throw new InvalidOperationException("The Entity is already registered, it cannot be modified"); if (this.Registered & isPrimaryKey) throw new ArgumentException("The Entity is already registered, you cannot add a primary key", "isPrimaryKey"); var attr = new FieldAttribute(); attr.FieldName = fieldName; attr.DataType = fieldType; attr.AllowsNulls = !isPrimaryKey; attr.IsPrimaryKey = isPrimaryKey; attr.IsIdentity = EntityAttribute.KeyScheme == KeyScheme.Identity & isPrimaryKey & this.Fields.KeyFields.Count <= 0; attr.Length = length; attr.RequireUniqueValue = requireUnique; attr.SearchOrder = searchOrder; this.Fields.Add(attr); if (this.Registered && EntityDefinitionChanged != null) EntityDefinitionChanged.Invoke(this, new EntityTypeChangedArgs(this, attr)); }
protected void AddField(FieldAttribute field) { Fields.Add(field); }
internal EntityTypeChangedArgs(EntityInfo info, FieldAttribute field) { EntityInfo = info; ReferenceAttribute = null; FieldAttribute = field; TableCreated = false; }
protected void AddFieldToEntity(EntityInfo entity, FieldAttribute field) { entity.Fields.Add(field); }
public override DynamicEntityDefinition DiscoverDynamicEntity(string entityName) { if (!TableExists(entityName)) { throw new EntityNotFoundException(entityName); } var connection = GetConnection(true); try { using (var cmd = GetNewCommandObject()) { cmd.Connection = connection; cmd.Transaction = CurrentTransaction; cmd.CommandText = string.Format("SELECT COLUMN_NAME, ORDINAL_POSITION, IS_NULLABLE, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE FROM information_schema.columns WHERE TABLE_NAME = '{0}' ORDER BY ORDINAL_POSITION", entityName); var fields = new List <FieldAttribute>(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var name = reader.GetString(0); var nullable = string.Compare(reader.GetString(2), "YES", true) == 0; var type = reader.GetString(3).ParseToDbType(); var field = new FieldAttribute() { DataType = type, FieldName = name, AllowsNulls = nullable, }; if (!reader.IsDBNull(4)) { field.Precision = Convert.ToInt32(reader.GetValue(4)); } if (!reader.IsDBNull(5)) { field.Scale = Convert.ToInt32(reader.GetValue(5)); } fields.Add(field); } } // get PK info cmd.CommandText = string.Format( "SELECT COLUMN_NAME, CONSTRAINT_TYPE " + "FROM information_schema.table_constraints t " + "LEFT JOIN information_schema.key_column_usage k " + "USING(constraint_name,table_schema,table_name) " + "WHERE TABLE_NAME = '{0}'", entityName); // result will be PRIMARY_KEY or UNIQUE using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var column = reader.GetString(0); var t = reader.GetString(1); var pk = t == "PRIMARY_KEY"; var unique = t == "UNIQUE"; var field = fields.FirstOrDefault(f => f.FieldName == column); if (pk) { field.IsPrimaryKey = true; } if (unique) { field.RequireUniqueValue = true; } } } var entityDefinition = new DynamicEntityDefinition(entityName, fields); RegisterEntityInfo(entityDefinition); return(entityDefinition); } } finally { DoneWithConnection(connection, true); } }
protected override string GetFieldCreationAttributes(EntityAttribute attribute, FieldAttribute field, Boolean MultiplePrimaryKeys) { StringBuilder sb = new StringBuilder(); switch (field.DataType) { case DbType.AnsiString: case DbType.AnsiStringFixedLength: case DbType.StringFixedLength: case DbType.String: if (field.Length > 0) { sb.AppendFormat("({0}) ", field.Length); } else { sb.AppendFormat("({0}) ", DefaultStringFieldSize); } break; case DbType.Decimal: int p = field.Precision == 0 ? DefaultNumericFieldPrecision : field.Precision; sb.AppendFormat("({0},{1}) ", p, field.Scale); break; } if (field.Default != null && field.Default.Length > 0) { sb.AppendFormat("DEFAULT {0} ", field.Default); } if (field.IsPrimaryKey) { if (!MultiplePrimaryKeys) { sb.Append("PRIMARY KEY "); } if (attribute.KeyScheme == KeyScheme.Identity) { throw new NotImplementedException(); //switch (field.DataType) //{ // case DbType.Int32: // case DbType.UInt32: // sb.Append(AutoIncrementFieldIdentifier + " "); // break; // case DbType.Guid: // sb.Append("ROWGUIDCOL "); // break; // default: // throw new FieldDefinitionException(attribute.NameInStore, field.FieldName, // string.Format("Data Type '{0}' cannot be marked as an Identity field", field.DataType)); //} } } if (!field.AllowsNulls) { sb.Append("NOT NULL "); } if (field.RequireUniqueValue) { sb.Append("UNIQUE "); } return(sb.ToString()); }
protected override void Insert(object item, bool insertReferences, IDbConnection connection, IDbTransaction transaction, bool checkUpdates) { var isDynamicEntity = item is DynamicEntity; string entityName = null; if (isDynamicEntity) { entityName = ((DynamicEntity)item).EntityName; if (!m_entities.HasEntity(entityName)) { throw new EntityNotFoundException(entityName); } } else { entityName = m_entities.GetNameForType(item.GetType()); } if (entityName == null) { throw new EntityNotFoundException(item.GetType()); } var entity = m_entities[entityName]; Boolean bInheritedConnection = connection != null; if (transaction == null && connection == null) { connection = GetConnection(false); } try { // CheckOrdinals(entityName); FieldAttribute identity = null; var command = GetInsertCommand(entityName); if (transaction == null) { command.Connection = connection as FbConnection; } else { command.Connection = transaction.Connection as FbConnection; command.Transaction = transaction as FbTransaction; } var keyScheme = Entities[entityName].EntityAttribute.KeyScheme; // TODO: fill the parameters foreach (var field in Entities[entityName].Fields) { if ((field.IsPrimaryKey) && ((keyScheme == KeyScheme.Identity) || field.IsIdentity)) { identity = field; continue; } else if (isDynamicEntity) { object value = null; if (entity.Fields[field.FieldName].DataType == DbType.Object) { if (entity.Serializer == null) { throw new MissingMethodException( string.Format("The field '{0}' requires a custom serializer/deserializer method pair in the '{1}' Entity", field.FieldName, entity.EntityName)); } value = entity.Serializer.Invoke(item, field.FieldName); } else { value = ((DynamicEntity)item)[field.FieldName]; } if (value == null) { command.Parameters[String.Format("@{0}", field.FieldName)].Value = DBNull.Value; } else { command.Parameters[String.Format("@{0}", field.FieldName)].Value = value; } } else { if (field.DataType == DbType.Object) { if (entity.Serializer == null) { throw new MissingMethodException( string.Format("The field '{0}' requires a custom serializer/deserializer method pair in the '{1}' Entity", field.FieldName, entityName)); } var value = entity.Serializer.Invoke(item, field.FieldName); if (value == null) { command.Parameters[String.Format("@{0}", field.FieldName)].Value = DBNull.Value; } else { command.Parameters[String.Format("@{0}", field.FieldName)].Value = value; } } else if (field.IsRowVersion) { // read-only, so do nothing } else if (field.PropertyInfo.PropertyType.UnderlyingTypeIs <TimeSpan>()) { // SQL Compact doesn't support Time, so we're convert to a DateTime both directions var value = field.PropertyInfo.GetValue(item, null); if (value == null) { command.Parameters[String.Format("@{0}", field.FieldName)].Value = DBNull.Value; } else { var timespanTicks = ((TimeSpan)value).Ticks; command.Parameters[String.Format("@{0}", field.FieldName)].Value = timespanTicks; } } else { var value = field.PropertyInfo.GetValue(item, null); if (value != null) { command.Parameters[String.Format("@{0}", field.FieldName)].Value = value; } } } } command.ExecuteNonQuery(); // did we have an identity field? If so, we need to update that value in the item if (identity != null) { int id = 0; if (transaction == null) { id = GetIdentity(connection); } else { id = GetIdentity(transaction); } if (isDynamicEntity) { ((DynamicEntity)item)[identity.FieldName] = id; } else { identity.PropertyInfo.SetValue(item, id, null); } } if (insertReferences) { // cascade insert any References // do this last because we need the PK from above foreach (var reference in Entities[entityName].References) { var valueArray = reference.PropertyInfo.GetValue(item, null); if (valueArray == null) { continue; } var fk = Entities[entityName].Fields.KeyField.PropertyInfo.GetValue(item, null); string et = null; if (reference.IsArray || reference.IsList) { foreach (var element in valueArray as System.Collections.IEnumerable) { if (et == null) { et = m_entities.GetNameForType(element.GetType()); } Entities[et].Fields[reference.ReferenceField].PropertyInfo.SetValue(element, fk, null); if (checkUpdates) { this.InsertOrUpdate(element, insertReferences, connection, transaction); } else { this.Insert(element, insertReferences, connection, transaction, false); } } } else { throw new NotImplementedException(); } } } } finally { if (!bInheritedConnection) { DoneWithConnection(connection, false); } } }
internal void Add(FieldAttribute field) { Add(field.FieldName, null, null); }
private void FillEntity(Action <int, object> setter, string entityName, Type itemType, object item, out FieldAttribute identity) { // The reason for this somewhat convoluted Action parameter is that while the SqlCeUpdateableRecord (from Insert) // and SqlCeResultSet (from Update) both contain a SetValue method, they don't share it on any common // interface. using an Action allows us to share this code anyway. identity = null; var keyScheme = Entities[entityName].EntityAttribute.KeyScheme; foreach (var field in Entities[entityName].Fields) { if (field.IsPrimaryKey) { switch (keyScheme) { case KeyScheme.Identity: identity = field; break; case KeyScheme.GUID: var value = GetInstanceValue(field, item); if (value.Equals(Guid.Empty)) { value = Guid.NewGuid(); SetInstanceValue(field, item, value); } setter(field.Ordinal, value); break; } } else if (field.DataType == DbType.Object) { // get serializer var serializer = GetSerializer(itemType); if (serializer == null) { throw new MissingMethodException( string.Format("The field '{0}' requires a custom serializer/deserializer method pair in the '{1}' Entity", field.FieldName, entityName)); } var value = serializer.Invoke(item, new object[] { field.FieldName }); if (value == null) { setter(field.Ordinal, DBNull.Value); } else { setter(field.Ordinal, value); } } else if (field.DataType == DbType.DateTime) { var dtValue = GetInstanceValue(field, item); if (dtValue.Equals(DateTime.MinValue)) { if ((!field.AllowsNulls) && (field.DefaultType != DefaultType.CurrentDateTime)) { dtValue = SqlDateTime.MinValue; setter(field.Ordinal, dtValue); } else { // let the null pass through } } else { setter(field.Ordinal, dtValue); } } else if (field.IsRowVersion) { // read-only, so do nothing } else { var iv = GetInstanceValue(field, item); if ((iv == DBNull.Value) && (field.DefaultValue != null)) { iv = field.DefaultValue; } setter(field.Ordinal, iv); } } }
/// <summary> /// Inserts the provided entity instance into the underlying data store. /// </summary> /// <param name="item"></param> /// <remarks> /// If the entity has an identity field, calling Insert will populate that field with the identity vale vefore returning /// </remarks> public override void OnInsert(object item, bool insertReferences) { string entityName; var itemType = item.GetType(); if (item is DynamicEntity) { entityName = (item as DynamicEntity).EntityName; } else { entityName = m_entities.GetNameForType(itemType); } var keyScheme = Entities[entityName].EntityAttribute.KeyScheme; if (entityName == null) { throw new EntityNotFoundException(item.GetType()); } if (insertReferences) { DoInsertReferences(item, entityName, keyScheme, true); } // we'll use table direct for inserts - no point in getting the query parser involved in this var connection = GetConnection(false); try { CheckOrdinals(entityName); FieldAttribute identity = null; using (var command = new SqlCeCommand()) { command.Connection = connection as SqlCeConnection; command.Transaction = CurrentTransaction as SqlCeTransaction; command.CommandText = entityName; command.CommandType = CommandType.TableDirect; using (var results = command.ExecuteResultSet(ResultSetOptions.Updatable)) { var record = results.CreateRecord(); FillEntity(record.SetValue, entityName, itemType, item, out identity); results.Insert(record); // did we have an identity field? If so, we need to update that value in the item if (identity != null) { var id = GetIdentity(connection); SetInstanceValue(identity, item, id); } if (insertReferences) { DoInsertReferences(item, entityName, keyScheme, false); } } command.Dispose(); } } finally { DoneWithConnection(connection, false); } }
public override DynamicEntityDefinition DiscoverDynamicEntity(string entityName) { if (!TableExists(entityName)) { throw new EntityNotFoundException(entityName); } var connection = GetConnection(true); try { using (var cmd = GetNewCommandObject()) { cmd.Connection = connection; cmd.Transaction = CurrentTransaction; cmd.CommandText = string.Format( "SELECT COLUMN_NAME, NULLABLE, DATA_TYPE, DATA_PRECISION, DATA_SCALE FROM all_tab_cols " + " WHERE UPPER(TABLE_NAME) = UPPER('{0}') ORDER BY COLUMN_ID", entityName); var fields = new List <FieldAttribute>(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var name = reader.GetString(0); var nullable = string.Compare(reader.GetString(1), "Y", true) == 0; var type = ParseDbType(reader.GetString(2)); var field = new FieldAttribute() { DataType = type, FieldName = name, AllowsNulls = nullable, }; if (!reader.IsDBNull(3)) { field.Precision = Convert.ToInt32(reader.GetValue(3)); } if (!reader.IsDBNull(4)) { field.Scale = Convert.ToInt32(reader.GetValue(4)); } fields.Add(field); } } //CONSTRAINT_TYPE (from 11gR2 docs) //C - Check constraint on a table //P - Primary key //U - Unique key //R - Referential integrity //V - With check option, on a view //O - With read only, on a view //H - Hash expression //F - Constraint that involves a REF column //S - Supplemental logging // INDEX_TYPE // ASC == NORMAL // DESC == FUNCTION-BASED NORMAL cmd.CommandText = string.Format( "SELECT cons.constraint_type, cons.constraint_name, cols.column_name, i.index_type " + "FROM all_constraints cons " + "LEFT OUTER JOIN all_cons_columns cols " + "ON cons.table_name = cols.table_name " + "LEFT OUTER JOIN all_indexes i " + "ON cons.index_name = i.index_name " + "WHERE UPPER(cols.table_name) = UPPER('{0}')" , entityName); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var column = reader.GetString(2); var ct = reader.GetString(0).TrimEnd(); var pk = false; var unique = false; switch (ct) { case "P": pk = true; unique = true; break; case "U": unique = true; break; } var field = fields.FirstOrDefault(f => f.FieldName == column); if (pk) { field.IsPrimaryKey = true; } else { var isdescending = reader.GetString(3).IndexOf("FUNTION-BASED", StringComparison.InvariantCultureIgnoreCase) >= 0; field.SearchOrder = isdescending ? FieldSearchOrder.Descending : FieldSearchOrder.Ascending; } if (unique) { field.RequireUniqueValue = true; } } } var entityDefinition = new DynamicEntityDefinition(entityName, fields); RegisterEntityInfo(entityDefinition); return(entityDefinition); } } finally { DoneWithConnection(connection, true); } }
public abstract bool FieldExists(EntityInfo entityInfo, FieldAttribute fieldInfo);
/// <summary> /// Inserts the provided entity instance into the underlying data store. /// </summary> /// <param name="item"></param> /// <remarks> /// If the entity has an identity field, calling Insert will populate that field with the identity vale vefore returning /// </remarks> protected override void Insert(object item, bool insertReferences, IDbConnection connection, IDbTransaction transaction, bool checkUpdates) { var isDynamicEntity = item is DynamicEntity; string entityName = null; if (isDynamicEntity) { entityName = ((DynamicEntity)item).EntityName; if (!m_entities.HasEntity(entityName)) { throw new EntityNotFoundException(entityName); } } else { entityName = m_entities.GetNameForType(item.GetType()); } if (entityName == null) { throw new EntityNotFoundException(item.GetType()); } var entity = m_entities[entityName]; Boolean bInheritedConnection = connection != null; if (transaction == null && connection == null) { connection = GetConnection(false); } try { OnBeforeInsert(item, insertReferences); var start = DateTime.Now; FieldAttribute identity = null; using (var command = new SqlCeCommand()) { if (transaction == null) { command.Connection = connection as SqlCeConnection; } else { command.Connection = transaction.Connection as SqlCeConnection; command.Transaction = transaction as SqlCeTransaction; } command.CommandText = entity.EntityName; command.CommandType = CommandType.TableDirect; using (var results = command.ExecuteResultSet(ResultSetOptions.Updatable)) { var ordinals = GetOrdinals(entityName, results); var record = results.CreateRecord(); var keyScheme = Entities[entity.EntityName].EntityAttribute.KeyScheme; foreach (var field in Entities[entity.EntityName].Fields) { if ((keyScheme == KeyScheme.Identity) && field.IsPrimaryKey) { identity = field; } else if (isDynamicEntity) { object value = null; if (entity.Fields[field.FieldName].DataType == DbType.Object) { if (entity.Serializer == null) { throw new MissingMethodException( string.Format("The field '{0}' requires a custom serializer/deserializer method pair in the '{1}' Entity", field.FieldName, entity.EntityName)); } value = entity.Serializer.Invoke(item, field.FieldName); } else { value = ((DynamicEntity)item)[field.FieldName]; } if (value == null) { record.SetValue(ordinals[field.FieldName], DBNull.Value); } else { record.SetValue(ordinals[field.FieldName], value); } } else { if (field.DataType == DbType.Object) { if (entity.Serializer == null) { throw new MissingMethodException( string.Format("The field '{0}' requires a custom serializer/deserializer method pair in the '{1}' Entity", field.FieldName, entity.EntityName)); } var value = entity.Serializer.Invoke(item, field.FieldName); if (value == null) { record.SetValue(ordinals[field.FieldName], DBNull.Value); } else { record.SetValue(ordinals[field.FieldName], value); } } else if (field.IsRowVersion) { // read-only, so do nothing } else if (field.PropertyInfo.PropertyType.UnderlyingTypeIs <TimeSpan>()) { // SQL Compact doesn't support Time, so we're convert to a DateTime both directions var value = field.PropertyInfo.GetValue(item, null); if (value == null) { record.SetValue(ordinals[field.FieldName], DBNull.Value); } else { var timespanTicks = ((TimeSpan)value).Ticks; record.SetValue(ordinals[field.FieldName], timespanTicks); } } else { var value = field.PropertyInfo.GetValue(item, null); record.SetValue(ordinals[field.FieldName], value); } } } results.Insert(record); // did we have an identity field? If so, we need to update that value in the item if (identity != null) { int id = 0; if (transaction == null) { id = GetIdentity(connection); } else { id = GetIdentity(transaction); } if (isDynamicEntity) { ((DynamicEntity)item)[identity.FieldName] = id; } else { identity.PropertyInfo.SetValue(item, id, null); } } if (insertReferences) { // cascade insert any References // do this last because we need the PK from above foreach (var reference in Entities[entity.EntityName].References) { var valueArray = reference.PropertyInfo.GetValue(item, null); if (valueArray == null) { continue; } // Modified - 2012.08.16 - Corrected an error where the bad keyfield was used. //var fk = Entities[entityName].Fields[reference.ReferenceField].PropertyInfo.GetValue(item, null); var fk = Entities[entity.EntityName].Fields.KeyField.PropertyInfo.GetValue(item, null); string et = null; if (reference.IsArray || reference.IsList) { foreach (var element in valueArray as System.Collections.IEnumerable) { if (et == null) { et = m_entities.GetNameForType(element.GetType()); } // Added - 2012.08.08 - Replacing the old code to handle existing objects which were added Entities[et].Fields[reference.ReferenceField].PropertyInfo.SetValue(element, fk, null); if (checkUpdates) { this.InsertOrUpdate(element, insertReferences, connection, transaction); } else { this.Insert(element, insertReferences, connection, transaction, checkUpdates); } } } else { throw new NotImplementedException(); } } } } } OnAfterInsert(item, insertReferences, DateTime.Now.Subtract(start), null); } finally { if (!bInheritedConnection) { DoneWithConnection(connection, false); } } }
protected override string GetFieldCreationAttributes(EntityAttribute attribute, FieldAttribute field) { switch (field.DataType) { case DbType.Guid: return("(16)"); // guids are "RAW(16)" default: return(base.GetFieldCreationAttributes(attribute, field)); } }
public override void OnInsert(object item, bool insertReferences) { if (item is DynamicEntity) { OnInsertDynamicEntity(item as DynamicEntity, insertReferences); return; } string entityName; var itemType = item.GetType(); entityName = m_entities.GetNameForType(itemType); if (entityName == null) { throw new EntityNotFoundException(item.GetType()); } var keyScheme = Entities[entityName].EntityAttribute.KeyScheme; // ---------- Handle N:1 References ------------- if (insertReferences) { DoInsertReferences(item, entityName, keyScheme, true); } var connection = GetConnection(false); try { FieldAttribute identity = null; keyScheme = Entities[entityName].EntityAttribute.KeyScheme; var command = GetInsertCommand(entityName); command.Connection = connection as OracleConnection; command.Transaction = CurrentTransaction as OracleTransaction; // TODO: fill the parameters foreach (var field in Entities[entityName].Fields) { if ((field.IsPrimaryKey) && (keyScheme == KeyScheme.Identity)) { identity = field; continue; } else if (field.DataType == DbType.Object) { // get serializer var serializer = GetSerializer(itemType); if (serializer == null) { throw new MissingMethodException( string.Format("The field '{0}' requires a custom serializer/deserializer method pair in the '{1}' Entity", field.FieldName, entityName)); } var value = serializer.Invoke(item, new object[] { field.FieldName }); if (value == null) { command.Parameters[field.FieldName].Value = DBNull.Value; } else { command.Parameters[field.FieldName].Value = value; } } else if (field.DataType == DbType.DateTime) { var dtValue = GetInstanceValue(field, item); if (dtValue.Equals(DateTime.MinValue) && ((field.AllowsNulls) || (field.DefaultType == DefaultType.CurrentDateTime))) { // testing of just letting the null fall through is setting the field to null, not using the default // so we'll set it manually dtValue = DateTime.Now; } command.Parameters[field.FieldName].Value = dtValue; } else if (field.DataType == DbType.Guid) { // read-only, so do nothing var guid = field.PropertyInfo.GetValue(item, null); if (guid == null) { command.Parameters[field.FieldName].Value = DBNull.Value; } else { command.Parameters[field.FieldName].Value = ((Guid)guid).ToByteArray(); } } else if (field.PropertyInfo.PropertyType.UnderlyingTypeIs <TimeSpan>()) { // SQL Compact doesn't support Time, so we're convert to a DateTime both directions var value = field.PropertyInfo.GetValue(item, null); if (value == null) { command.Parameters[field.FieldName].Value = DBNull.Value; } else { var timespanTicks = ((TimeSpan)value).Ticks; command.Parameters[field.FieldName].Value = timespanTicks; } } else { var value = field.PropertyInfo.GetValue(item, null); if (value == null) { if (field.DefaultValue != null) { command.Parameters[field.FieldName].Value = field.DefaultValue; } else { command.Parameters[field.FieldName].Value = DBNull.Value; } } else { command.Parameters[field.FieldName].Value = value; } } } // did we have an identity field? If so, we need to update that value in the item if (identity == null) { command.ExecuteNonQuery(); } else { var idParameter = new OracleParameter(":LASTID", OracleDbType.Int32); idParameter.Direction = ParameterDirection.Output; command.Parameters.Add(idParameter); command.ExecuteNonQuery(); identity.PropertyInfo.SetValue(item, idParameter.Value, null); } if (insertReferences) { // ---------- Handle 1:N References ------------- DoInsertReferences(item, entityName, keyScheme, false); } } catch (Exception ex) { Debug.WriteLine(ex.Message); if (Debugger.IsAttached) { Debugger.Break(); } throw; } finally { DoneWithConnection(connection, false); } }
public override DynamicEntityDefinition DiscoverDynamicEntity(string entityName) { if (!TableExists(entityName)) { return(null); } var connection = GetConnection(true); try { using (var cmd = GetNewCommandObject()) { cmd.Connection = connection; cmd.Transaction = CurrentTransaction; cmd.CommandText = string.Format("SELECT COLUMN_NAME, ORDINAL_POSITION, IS_NULLABLE, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE FROM information_schema.columns WHERE TABLE_NAME = '{0}' ORDER BY ORDINAL_POSITION", entityName); var fields = new List <FieldAttribute>(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var name = reader.GetString(0); var nullable = string.Compare(reader.GetString(2), "YES", true) == 0; var type = reader.GetString(3).ParseToDbType(); var field = new FieldAttribute() { DataType = type, FieldName = name, AllowsNulls = nullable, }; if (!reader.IsDBNull(4)) { field.Precision = Convert.ToInt32(reader.GetValue(4)); } if (!reader.IsDBNull(5)) { field.Scale = Convert.ToInt32(reader.GetValue(5)); } fields.Add(field); } } cmd.CommandText = string.Format("SELECT COLUMN_NAME, PRIMARY_KEY, [UNIQUE], COLLATION FROM information_schema.indexes WHERE TABLE_NAME = '{0}'", entityName); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var column = reader.GetString(0); var pk = Convert.ToBoolean(reader.GetValue(1)); var unique = Convert.ToBoolean(reader.GetValue(2)); var field = fields.FirstOrDefault(f => f.FieldName == column); if (pk) { field.IsPrimaryKey = true; } else { var collation = Convert.ToInt32(reader.GetValue(3)); field.SearchOrder = collation == 1 ? FieldSearchOrder.Ascending : FieldSearchOrder.Descending; } if (unique) { field.RequireUniqueValue = true; } } } var entityDefinition = new DynamicEntityDefinition(entityName, fields); RegisterEntityInfo(entityDefinition); return(entityDefinition); } } finally { DoneWithConnection(connection, true); } }
public EntityInfo[] GetEntityDefinitions() { ValidateConnection(); var entities = new List<EntityInfo>(); using (var connection = new SqlCeConnection(m_connectionString)) using (var cmd = new SqlCeCommand(GetTablesSQL, connection)) { connection.Open(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var info = new EntityInfo(); var indexInfo = new Dictionary<string, IndexInfo>(); info.Entity = new EntityAttribute(); info.Entity.NameInStore = reader.GetString(0); using(var indexCommand = new SqlCeCommand( string.Format("SELECT INDEX_NAME, PRIMARY_KEY, COLUMN_NAME, COLLATION FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME = '{0}'", info.Entity.NameInStore), connection)) using (var indexReader = indexCommand.ExecuteReader()) { while(indexReader.Read()) { var indexName = indexReader.GetString(0); var primaryKey = indexReader.GetBoolean(1); var columnName = indexReader.GetString(2); var sortOrder = indexReader.GetInt16(3) == 1 ? FieldOrder.Ascending : FieldOrder.Descending; // collation of 1 == ascending, 2 == descending (based on a quick test, this might be incorrect) // TODO: handle cases where a column is in multiple indexes (ORM doesn't support that scenario for now) if (!indexInfo.ContainsKey(columnName)) { indexInfo.Add(columnName, new IndexInfo() { ColumnName = columnName, IndexName = indexName, PrimaryKey = primaryKey, SearchOrder = sortOrder }); } } } // TODO: look for primary key to set key scheme info.Entity.KeyScheme = KeyScheme.None; using (var fieldCommand = new SqlCeCommand( string.Format("SELECT COLUMN_NAME, COLUMN_HASDEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, AUTOINC_SEED FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{0}'", info.Entity.NameInStore), connection)) { using (var fieldReader = fieldCommand.ExecuteReader()) { while (fieldReader.Read()) { var field = new FieldAttribute(); field.FieldName = fieldReader.GetString(0); field.AllowsNulls = string.Compare(fieldReader.GetString(2), "YES", true) == 0; field.DataType = fieldReader.GetString(3).ParseToDbType(); object val = fieldReader[4]; if(!val.Equals(DBNull.Value)) { field.Length = Convert.ToInt32(val); } val = fieldReader[5]; if (!val.Equals(DBNull.Value)) { field.Precision = Convert.ToInt32(val); } val = fieldReader[6]; if (!val.Equals(DBNull.Value)) { field.Scale = Convert.ToInt32(val); } val = fieldReader[7]; if (!val.Equals(DBNull.Value)) { // identity field, so it must be the PK (or part of it) info.Entity.KeyScheme = KeyScheme.Identity; } // check for indexes if (indexInfo.ContainsKey(field.FieldName)) { var idx = indexInfo[field.FieldName]; if (idx.PrimaryKey) { field.IsPrimaryKey = true; if (field.DataType == DbType.Guid) { info.Entity.KeyScheme = KeyScheme.GUID; } } field.SearchOrder = idx.SearchOrder; } // TODO: populate the remainder of the field info info.Fields.Add(field); } } } entities.Add(info); } } } return entities.ToArray(); }
public static Field GetFieldForAttribute(FieldAttribute attrib, KeyScheme keyScheme) { Field field = null; switch (attrib.DataType) { case System.Data.DbType.Int32: field = new Field <int>(attrib.FieldName); if (attrib.IsPrimaryKey) { if (keyScheme == KeyScheme.Identity) { // As of 10/28/2013, if a field is a PK, DreamFactory forces it to be an auto-incrementing number field.IsPrimaryKey = true; field.AutoIncrement = true; } } break; case System.Data.DbType.Int64: field = new Field <long>(attrib.FieldName); break; case System.Data.DbType.Byte: field = new Field <byte>(attrib.FieldName); break; case System.Data.DbType.Int16: field = new Field <short>(attrib.FieldName); break; case System.Data.DbType.String: case System.Data.DbType.StringFixedLength: field = new Field <string>(attrib.FieldName); if (attrib.Length <= 0) { field.Length = DefaultStringLength; } else if (attrib.Length > MaxStringLength) { field.Length = MaxStringLength; } else { field.Length = attrib.Length; } break; case System.Data.DbType.Boolean: field = new Field <bool>(attrib.FieldName); break; case System.Data.DbType.Single: field = new Field <float>(attrib.FieldName); field.Scale = attrib.Scale <= 0 ? DefaultDoubleScale : attrib.Scale; field.Precision = attrib.Precision <= 0 ? DefaultDoublePrecision : attrib.Precision; break; case System.Data.DbType.Double: field = new Field <double>(attrib.FieldName); field.Scale = attrib.Scale <= 0 ? DefaultDoubleScale : attrib.Scale; field.Precision = attrib.Precision <= 0 ? DefaultDoublePrecision : attrib.Precision; break; case System.Data.DbType.Decimal: field = new Field <decimal>(attrib.FieldName); // field.Scale = attrib.Scale; // field.Precision = attrib.Precision; break; case System.Data.DbType.DateTime: field = new Field <DateTime>(attrib.FieldName); break; case System.Data.DbType.Time: field = new Field <TimeSpan>(attrib.FieldName); break; case System.Data.DbType.Guid: case System.Data.DbType.Binary: field = new Field <byte[]>(attrib.FieldName); break; default: if (Debugger.IsAttached) { Debugger.Break(); } throw new NotSupportedException(string.Format("Field type '{0}' is not supported.", attrib.DataType.ToString())); } field.AllowsNull = attrib.AllowsNulls; return(field); }
protected override Boolean FieldExists(IDbConnection connection, EntityInfo entity, FieldAttribute field) { Boolean exists = false; try { // ANSI SQL way. Works in PostgreSQL, MSSQL, MySQL. using (var command = GetNewCommandObject()) { command.CommandText = String.Format("select count(*) from Information_SCHEMA.columns where table_name='{0}' and column_name='{1}'", entity.EntityName, field.FieldName); command.Connection = connection; exists = (int)command.ExecuteScalar() > 0; } } catch { try { exists = true; //TODO: Bad practice, but works across all DBs, need to work on a better test using (var command = GetNewCommandObject()) { command.CommandText = String.Format("select {1} from {0} where 1 = 0", entity.EntityName, field.FieldName); command.Connection = connection; command.ExecuteNonQuery(); } } catch { exists = false; } } return(exists); }
/// <summary> /// Inserts the provided entity instance into the underlying data store. /// </summary> /// <param name="item"></param> /// <remarks> /// If the entity has an identity field, calling Insert will populate that field with the identity vale vefore returning /// </remarks> public override void OnInsert(object item, bool insertReferences) { if (item is DynamicEntity) { OnInsertDynamicEntity(item as DynamicEntity, insertReferences); return; } var itemType = item.GetType(); string entityName = m_entities.GetNameForType(itemType); var keyScheme = Entities[entityName].EntityAttribute.KeyScheme; if (entityName == null) { throw new EntityNotFoundException(item.GetType()); } // ---------- Handle N:1 References ------------- if (insertReferences) { DoInsertReferences(item, entityName, keyScheme, true); } var connection = GetConnection(false); try { FieldAttribute identity = null; var command = GetInsertCommand(entityName); command.Connection = connection as SQLiteConnection; command.Transaction = CurrentTransaction as SQLiteTransaction; // TODO: fill the parameters foreach (var field in Entities[entityName].Fields) { if ((field.IsPrimaryKey) && (keyScheme == KeyScheme.Identity)) { identity = field; continue; } else if (field.DataType == DbType.Object) { // get serializer var serializer = GetSerializer(itemType); if (serializer == null) { throw new MissingMethodException( string.Format("The field '{0}' requires a custom serializer/deserializer method pair in the '{1}' Entity", field.FieldName, entityName)); } var value = serializer.Invoke(item, new object[] { field.FieldName }); if (value == null) { command.Parameters[ParameterPrefix + field.FieldName].Value = DBNull.Value; } else { command.Parameters[ParameterPrefix + field.FieldName].Value = value; } } else if (field.DataType == DbType.DateTime) { var dtValue = GetInstanceValue(field, item); if (dtValue.Equals(DateTime.MinValue) && ((field.AllowsNulls) || (field.DefaultType == DefaultType.CurrentDateTime))) { // testing of just letting the null fall through is setting the field to null, not using the default // so we'll set it manually dtValue = DateTime.Now; } command.Parameters[ParameterPrefix + field.FieldName].Value = dtValue; } else if (field.IsRowVersion) { // read-only, so do nothing } else if (field.PropertyInfo.PropertyType.UnderlyingTypeIs <TimeSpan>()) { // SQLite doesn't support "timespan" - and date/time must be stored as text, real or 64-bit integer (see the SQLite docs for more details) // here we'll store TimeSpans (since they can be negative) as an offset from a base date var value = field.PropertyInfo.GetValue(item, null); if (value == null) { command.Parameters[ParameterPrefix + field.FieldName].Value = DBNull.Value; } else { var storeTime = new DateTime(1980, 1, 1) + (TimeSpan)value; command.Parameters[ParameterPrefix + field.FieldName].Value = storeTime; } } else { var value = field.PropertyInfo.GetValue(item, null); if ((value == null) && (field.DefaultValue != null)) { command.Parameters[ParameterPrefix + field.FieldName].Value = field.DefaultValue; } else { command.Parameters[ParameterPrefix + field.FieldName].Value = value; } } } command.ExecuteNonQuery(); // did we have an identity field? If so, we need to update that value in the item if (identity != null) { var id = GetIdentity(connection); identity.PropertyInfo.SetValue(item, id, null); } if (insertReferences) { // ---------- Handle 1:N References ------------- DoInsertReferences(item, entityName, keyScheme, false); } } finally { DoneWithConnection(connection, false); } }
public override DynamicEntityDefinition DiscoverDynamicEntity(string entityName) { if (!TableExists(entityName)) { return(null); } var connection = GetConnection(true); try { using (var cmd = GetNewCommandObject()) { cmd.Connection = connection; cmd.Transaction = CurrentTransaction; cmd.CommandText = string.Format("PRAGMA table_info({0})", entityName); // cid, name, type, notnull, dflt_value, pk var fields = new List <FieldAttribute>(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var cid = reader.GetInt64(0); var name = reader.GetString(1); var type = reader.GetString(2).ParseToDbType(); var nullable = reader.GetInt64(3) == 0; // 4 == default value - TODO var isPK = reader.GetInt64(5) == 1; var field = new FieldAttribute() { DataType = type, FieldName = name, AllowsNulls = nullable, IsPrimaryKey = isPK }; fields.Add(field); } } cmd.CommandText = string.Format("SELECT 1 FROM sqlite_master WHERE tbl_name='{0}' AND sql LIKE '%AUTOINCREMENT%'", entityName); var autoIncrement = cmd.ExecuteScalar(); // TODO: handle index metadata (ascending/descending, unique, etc) // PRAGMA index_list(TABLENAME) // seq | name | unique // PRAGMA index_info(INDEXNAME) // seqno | cid | name | var entityDefinition = new DynamicEntityDefinition(entityName, fields); try { if (Convert.ToInt64(autoIncrement) == 1L) { entityDefinition.EntityAttribute.KeyScheme = KeyScheme.Identity; } } catch { // not auto-increment } RegisterEntityInfo(entityDefinition); return(entityDefinition); } } finally { DoneWithConnection(connection, true); } }
public void AddField(FieldAttribute field) { Fields.Add(field); }
public override DynamicEntityDefinition DiscoverDynamicEntity(string entityName) { if (!TableExists(entityName)) { return(null); } var connection = GetConnection(true); try { using (var cmd = GetNewCommandObject()) { cmd.Connection = connection; cmd.Transaction = CurrentTransaction; cmd.CommandText = string.Format("SELECT COLUMN_NAME, ORDINAL_POSITION, IS_NULLABLE, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE, CHARACTER_MAXIMUM_LENGTH " + "FROM information_schema.columns WHERE TABLE_NAME = '{0}' ORDER BY ORDINAL_POSITION", entityName); var fields = new List <FieldAttribute>(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var name = reader.GetString(0); var nullable = string.Compare(reader.GetString(2), "YES", true) == 0; var type = reader.GetString(3).ParseToDbType(); var field = new FieldAttribute() { DataType = type, FieldName = name, AllowsNulls = nullable, }; if (!reader.IsDBNull(4)) { field.Precision = Convert.ToInt32(reader.GetValue(4)); } if (!reader.IsDBNull(5)) { field.Scale = Convert.ToInt32(reader.GetValue(5)); } if (!reader.IsDBNull(6)) { field.Length = Convert.ToInt32(reader.GetValue(6)); } fields.Add(field); } } cmd.CommandText = string.Format( "SELECT ac.name, ind.is_primary_key, ind.is_unique, ic.is_descending_key, col.collation_name, idc.name " + "FROM sys.indexes ind " + "INNER JOIN sys.index_columns ic " + " ON ind.object_id = ic.object_id and ind.index_id = ic.index_id " + "INNER JOIN sys.columns col " + " ON ic.object_id = col.object_id and ic.column_id = col.column_id " + "INNER JOIN sys.tables t " + " ON ind.object_id = t.object_id " + "INNER JOIN sys.identity_columns idc " + " ON col.object_id = idc.object_id and col.column_id = idc.column_id " + "INNER JOIN sys.columns ac " + " ON ac.object_id = col.object_id and ac.column_id = col.column_id " + "WHERE t.name = '{0}'", entityName); string identiyColumn = null; using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var column = reader.GetString(0); var pk = Convert.ToBoolean(reader.GetValue(1)); var unique = Convert.ToBoolean(reader.GetValue(2)); var field = fields.FirstOrDefault(f => f.FieldName == column); if (pk) { field.IsPrimaryKey = true; } else { var isdescending = Convert.ToInt32(reader.GetValue(3)); field.SearchOrder = isdescending == 0 ? FieldSearchOrder.Ascending : FieldSearchOrder.Descending; } if (unique) { field.RequireUniqueValue = true; } identiyColumn = reader.GetString(5); } } var entityDefinition = new DynamicEntityDefinition( entityName, fields, string.IsNullOrEmpty(identiyColumn) ? KeyScheme.None : KeyScheme.Identity); RegisterEntityInfo(entityDefinition); return(entityDefinition); } } finally { DoneWithConnection(connection, true); } }
private Dictionary <string, object> GetEntityValueDictionary(object item, out FieldAttribute identityField) { var entityName = GetEntityNameForInstance(item); var values = new Dictionary <string, object>(); identityField = null; if (item is DynamicEntity) { var de = item as DynamicEntity; foreach (var field in Entities[entityName].Fields) { if ((field.IsPrimaryKey) && (Entities[entityName].EntityAttribute.KeyScheme == KeyScheme.Identity)) { identityField = field; } var value = de.Fields[field.FieldName]; if ((field.AllowsNulls) && (value == null)) { values.Add(field.FieldName, null); } else { switch (field.DataType) { case System.Data.DbType.Time: values.Add(field.FieldName, ((TimeSpan)value).ToString()); break; case System.Data.DbType.Date: case System.Data.DbType.DateTime: case System.Data.DbType.DateTime2: values.Add(field.FieldName, Convert.ToDateTime(value).ToString("s")); break; default: values.Add(field.FieldName, value); break; } } } } else { foreach (var field in Entities[entityName].Fields) { if (field.IsPrimaryKey) { identityField = field; } var value = field.PropertyInfo.GetValue(item, null); if ((field.AllowsNulls) && (value == null)) { values.Add(field.FieldName, null); } else { switch (field.DataType) { case System.Data.DbType.Time: values.Add(field.FieldName, ((TimeSpan)value).ToString()); break; case System.Data.DbType.Date: case System.Data.DbType.DateTime: case System.Data.DbType.DateTime2: values.Add(field.FieldName, Convert.ToDateTime(value).ToString("s")); break; default: values.Add(field.FieldName, value); break; } } } } return(values); }
protected override Boolean FieldExists(IDbConnection connection, EntityInfo entity, FieldAttribute field) { Boolean exists = false; try { using (var command = GetNewCommandObject()) { command.CommandText = String.Format("PRAGMA table_info('{0}')", entity.EntityName, field.FieldName); OnSqlStatementCreated(command, null); command.Connection = connection; using (var results = command.ExecuteReader()) { while (results.Read()) { if (results["name"].ToString().Equals(field.FieldName)) { exists = true; break; } } } } } catch { try { exists = true; //TODO: Bad practice, but works across all DBs, need to work on a better test using (var command = GetNewCommandObject()) { command.CommandText = String.Format("select {1} from {0} where 1 = 0", entity.EntityName, field.FieldName); command.Connection = connection; command.ExecuteNonQuery(); } } catch { exists = false; } } return(exists); }
private CodeAttributeArgument[] GenerateFieldArguments(FieldAttribute field) { var attrList = new List<CodeAttributeArgument>(); // TODO add precision, etc. if (field.IsPrimaryKey) { attrList.Add(new CodeAttributeArgument(new CodeSnippetExpression("IsPrimaryKey=true"))); } if (field.SearchOrder != FieldOrder.None) { attrList.Add(new CodeAttributeArgument(new CodeSnippetExpression("SearchOrder=FieldSearchOrder." + field.SearchOrder.ToString()))); } return attrList.ToArray(); }