/// <summary> /// Returns the current domain model as "insert into" from another database with the same structure. /// The tables will be unordered (add your constraints afterwards) and remember to tweak each table as needed /// </summary> internal static string GetTransferScript <T>(string otherDatabaseName, params ExpressionProperty[] toSkip) { var tables = new StringBuilder(); var manyToManyTables = new StringBuilder(); foreach (var type in DwarfHelper.GetValidTypes <T>()) { var typeProps = (DwarfHelper.GetDBProperties(type).Union(DwarfHelper.GetGemListProperties(type))).Where(x => !toSkip.Contains(x)).Flatten(x => "[" + (x.PropertyType.Implements <IDwarf>() ? x.Name + "Id" : x.Name) + "], "); typeProps = typeProps.TruncateEnd(2); tables.AppendLine(string.Format("INSERT INTO [{0}] ({1}) (SELECT {1} from [{2}].dbo.[{0}])", type.Name, typeProps, otherDatabaseName)); foreach (var ep in DwarfHelper.GetManyToManyProperties(type)) { var tableName = ManyToManyAttribute.GetTableName(type, ep.ContainedProperty); if (manyToManyTables.ToString().Contains(tableName)) { continue; } var m2mProps = "[" + type.Name + "Id], [" + ep.PropertyType.GetGenericArguments()[0].Name + "Id]"; manyToManyTables.AppendLine(string.Format("INSERT INTO [{0}] ({1}) (SELECT {1} from [{2}].dbo.[{0}])", tableName, m2mProps, otherDatabaseName)); } } return(tables.ToString() + manyToManyTables); }
public void TestSignedLEB128(long value) { var stream = new MemoryStream(); { // check positive stream.WriteILEB128(value); Assert.AreEqual((uint)stream.Position, DwarfHelper.SizeOfILEB128(value)); stream.Position = 0; var readbackValue = stream.ReadSignedLEB128(); Assert.AreEqual(value, readbackValue); } { stream.Position = 0; // Check negative value = -value; stream.WriteILEB128(value); Assert.AreEqual((uint)stream.Position, DwarfHelper.SizeOfILEB128(value)); stream.Position = 0; var readbackValue = stream.ReadSignedLEB128(); Assert.AreEqual(value, readbackValue); } }
/// <summary> /// Creates unique constraints for the supplied type /// </summary> internal static void CreateUniqueConstraint <T>(StringBuilder constraints, Type type) { foreach (var uniqueGroupName in DwarfHelper.GetUniqueGroupNames <T>(type)) { CreateUniqueConstraint <T>(constraints, type, uniqueGroupName); } }
/// <summary> /// Builds and executes insert statement /// </summary> public virtual void Insert <T, TY>(Dwarf <TY> dwarf, Guid?customId = null) where TY : Dwarf <TY>, new() { var type = DbContextHelper <T> .ClearCacheForType(DwarfHelper.DeProxyfy(dwarf)); dwarf.Id = customId ?? Guid.NewGuid(); ExecuteNonQuery <T, TY>(new QueryBuilder <T>().InsertInto(type).Values(dwarf)); dwarf.IsSaved = true; }
/// <summary> /// Creates unique constraints for the supplied type and group name /// </summary> internal static void CreateUniqueConstraint <T>(StringBuilder constraints, Type type, string uniqueGroupName) { var constraintName = "UQ_" + type.Name + "_" + uniqueGroupName; var columns = DwarfHelper.GetUniqueGroupProperties <T>(type, uniqueGroupName).Select(x => QueryBuilder.GetColumnName(x.ContainedProperty)). Aggregate(String.Empty, (s, x) => s + ", [" + x + "]").Remove(0, 2); var alterTable = "ALTER TABLE [" + type.Name + "] ADD CONSTRAINT [" + constraintName + "] UNIQUE (" + columns + ")"; constraints.AppendLine(alterTable); }
/// <summary> /// Builds and executes an update statement /// </summary> public virtual void Update <T>(Dwarf <T> dwarf, IEnumerable <ExpressionProperty> properties) where T : Dwarf <T>, new() { var type = DbContextHelper <T> .ClearCacheForType(DwarfHelper.DeProxyfy(dwarf)); var command = new QueryBuilder <T>() .Update(type) .Set(dwarf, properties) .Where(dwarf, Cfg.PKProperties[type]); ExecuteNonQuery <T>(command); }
/// <summary> /// Generates create table commands for the supplied type /// </summary> internal static void CreateTable <T>(StringBuilder tables, Type type, StringBuilder constraints, StringBuilder manyToManyTables) { tables.AppendLine("CREATE TABLE [" + type.Name + "] ( "); foreach (var pi in DwarfHelper.GetDBProperties(type)) { tables.AppendLine(TypeToColumnName(pi) + " " + TypeToColumnConstruction(type, pi.ContainedProperty)); } foreach (var pi in DwarfHelper.GetGemListProperties(type)) { tables.AppendLine(TypeToColumnName(pi) + " " + TypeToColumnConstruction(type, pi.ContainedProperty)); } foreach (var manyToManyProperty in DwarfHelper.GetManyToManyProperties(type)) { CreateManyToManyTable(type, manyToManyProperty, manyToManyTables, constraints); } var keys = String.Empty; foreach (var propertyInfo in DwarfHelper.GetPKProperties(type)) { keys += TypeToColumnName(propertyInfo) + ", "; } if (!string.IsNullOrEmpty(keys)) { keys = keys.TruncateEnd(2); keys = "CONSTRAINT [PK_" + type.Name + "] PRIMARY KEY (" + keys + ")"; tables.AppendLine(keys); } foreach (var pi in DwarfHelper.GetFKProperties <T>(type)) { var constraintName = "FK_" + type.Name + "_" + pi.Name; var alterTable = "ALTER TABLE [" + type.Name + "] ADD CONSTRAINT [" + constraintName + "Id] FOREIGN KEY (" + pi.Name + "Id) REFERENCES [" + pi.PropertyType.Name + "] (Id)"; if (!DwarfPropertyAttribute.GetAttribute(pi.ContainedProperty).DisableDeleteCascade) { alterTable += " ON DELETE CASCADE "; } constraints.AppendLine(alterTable); } CreateUniqueConstraint <T>(constraints, type); tables.AppendLine(") "); tables.AppendLine(); }
/// <summary> /// Builds and executes a delete statement /// </summary> public virtual void Delete <T>(Dwarf <T> dwarf) where T : Dwarf <T>, new() { var type = DbContextHelper <T> .ClearCacheForType(DwarfHelper.DeProxyfy(dwarf)); var command = new QueryBuilder <T>() .DeleteFrom <T>() .Where(dwarf, Cfg.PKProperties[type]); ExecuteNonQuery <T>(command); dwarf.IsSaved = false; }
/// <summary> /// Converts and returns the current domain model as create scripts (incl keys) /// </summary> internal static string GetCreateScript <T>(string connectionString = null, bool hideOptionalStuff = false) { var tables = new StringBuilder(); var constraints = new StringBuilder(); var manyToManyTables = new StringBuilder(); foreach (var type in DwarfHelper.GetValidTypes <T>()) { CreateTable <T>(tables, type, constraints, manyToManyTables); } return(tables.ToString() + manyToManyTables + constraints); }
public void TestLEB128(ulong value) { var stream = new MemoryStream(); stream.WriteULEB128(value); Assert.AreEqual((uint)stream.Position, DwarfHelper.SizeOfULEB128(value)); stream.Position = 0; var readbackValue = stream.ReadULEB128(); Assert.AreEqual(value, readbackValue); }
private static string GetDropConstraintsScript <T>() { var constraints = new StringBuilder(); foreach (var type in DwarfHelper.GetValidTypes <T>()) { foreach (var pi in DwarfHelper.GetFKProperties <T>(type)) { var fk = "FK_" + type.Name + "_" + pi.Name + "Id"; constraints.AppendLine("IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + fk + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + fk + "]"); } } return(constraints.ToString()); }
private static IEnumerable <string> GetCurrentManyToManyTables(IEnumerable <Type> allTypes) { foreach (var type in allTypes) { foreach (var pi in DwarfHelper.GetManyToManyProperties(type)) { var value = ManyToManyAttribute.GetTableName(type, pi.ContainedProperty); if (!string.IsNullOrEmpty(value)) { yield return(value); } } } }
public TY Select <T, TY>(params WhereCondition <TY>[] conditions) where TY : Dwarf <TY>, new() { if (!typeof(TY).Implements <ICompositeId>()) { throw new InvalidOperationException("Use Select for non-CompositeId types"); } var command = new QueryBuilder() .Select <TY>() .From <TY>() .Where(conditions).ToQuery(); var uniqueKey = DwarfHelper.GetUniqueKeyForCompositeId(conditions); TY result = null; if (!typeof(TY).Implements <ICacheless>() && CacheManager.TryGetCache(uniqueKey, out result)) { return(result); } var sdr = (SqlDataReader)ExecuteReader <T, TY>(command); try { result = sdr.Read() ? TupleToObject <TY>(sdr) : null; } catch (Exception e) { DwarfContext <T> .GetConfiguration().ErrorLogService.Logg(e); } finally { sdr.Close(); } if (typeof(TY).Implements <ICacheless>()) { return(result); } return(result != null ? CacheManager.SetCache(DwarfHelper.GetUniqueKeyForCompositeId(result), result) : CacheManager.SetCache(DwarfHelper.GetUniqueKeyForCompositeId(conditions), (TY)null)); }
private static string GetDropTablesScript <T>() { var tables = new StringBuilder(); var manyToManyTables = new StringBuilder(); foreach (var type in DwarfHelper.GetValidTypes <T>()) { foreach (var manyToManyProperty in DwarfHelper.GetManyToManyProperties(type)) { var tableName = ManyToManyAttribute.GetTableName(type, manyToManyProperty.ContainedProperty); if (!manyToManyTables.ToString().Contains("DROP TABLE [" + tableName + "]")) { manyToManyTables.AppendLine("IF EXISTS (SELECT * FROM dbo.sysobjects WHERE Id = OBJECT_ID(N'[" + tableName + "]') AND OBJECTPROPERTY(Id, N'IsUserTable') = 1) DROP Table [" + tableName + "]"); } } if (type.Implements <IDwarf>() && !type.IsAbstract) { tables.AppendLine("IF EXISTS (SELECT * FROM dbo.sysobjects WHERE Id = OBJECT_ID(N'[" + type.Name + "]') AND OBJECTPROPERTY(Id, N'IsUserTable') = 1) DROP Table [" + type.Name + "]"); } } return(manyToManyTables.ToString() + tables); }
/// <summary> /// See base /// </summary> public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return(null); } if (reader.TokenType == JsonToken.String) { var val = reader.Value; if (val != null && !string.IsNullOrEmpty(val.ToString())) { return(DwarfHelper.Load(objectType, Guid.Parse(val.ToString()))); } return(null); } var jObject = JObject.Load(reader); object obj = null; if (jObject.Property("id") != null) { var id = jObject.Property("id").Value.ToObject <Guid?>(); if (id.HasValue) { obj = DwarfHelper.Load(objectType, id.Value); } if (obj == null) { if (HttpContext.Current.Items.Contains(id.Value.ToString())) { obj = HttpContext.Current.Items[id.Value.ToString()]; } else { obj = DwarfHelper.CreateInstance(objectType); ((IDwarf)obj).Id = id; HttpContext.Current.Items[id.Value.ToString()] = obj; } } } else { obj = DwarfHelper.CreateInstance(objectType); } if (obj == null) { throw new JsonSerializationException("No object created."); } var writer = new StringWriter(); serializer.Serialize(writer, jObject); using (var newReader = new JsonTextReader(new StringReader(writer.ToString()))) { newReader.Culture = reader.Culture; newReader.DateParseHandling = reader.DateParseHandling; newReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; newReader.FloatParseHandling = reader.FloatParseHandling; serializer.Populate(newReader, obj); } return(obj); }
/// <summary> /// Bulk inserts the supplied objects using SqlBulkCopy /// </summary> public virtual void BulkInsert <T>(IEnumerable <T> objects) where T : Dwarf <T>, new() { var list = objects.ToList(); if (!list.Any()) { return; } var properties = DwarfHelper.GetDBProperties <T>().ToList(); var dt = new DataTable(); foreach (var pi in properties) { if (pi.PropertyType.Implements <IDwarf>()) { dt.Columns.Add(pi.Name + "Id", typeof(Guid)); } else if (pi.PropertyType.IsEnum()) { dt.Columns.Add(pi.Name, typeof(string)); } else { dt.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType); } } Parallel.ForEach(list, obj => { if (obj.IsSaved) { return; } obj.Id = obj.Id.HasValue ? obj.Id.Value : Guid.NewGuid(); var row = new object[properties.Count]; for (var i = 0; i < properties.Count; i++) { var value = properties[i].GetValue(obj); if (properties[i].PropertyType.Implements <IDwarf>()) { if (value != null) { row[i] = ((IDwarf)value).Id; } else { row[i] = DBNull.Value; } } else { row[i] = value ?? DBNull.Value; } } obj.IsSaved = true; lock (dt.Rows.SyncRoot) dt.Rows.Add(row); }); var con = (SqlConnection)DbContextHelper <T> .OpenConnection(); var copy = new SqlBulkCopy(con, SqlBulkCopyOptions.Default, (SqlTransaction)DbContextHelper <T> .Transaction) { DestinationTableName = typeof(T).Name, BulkCopyTimeout = 10000, BatchSize = 2500, }; foreach (DataColumn column in dt.Columns) { copy.ColumnMappings.Add(column.ColumnName, column.ColumnName); } copy.WriteToServer(dt); if (con != DbContextHelper <T> .Connection) { con.Dispose(); } objects.ForEachX(x => x.IsSaved = true); }
/// <summary> /// Analyses the current domain model and database and generates update scripts in an attempt to synchronize them. /// Note that a few places might need manual coding, such as when columns become not nullable, when target types changes, etc. Look for "Warning!!" /// in the generated code /// </summary> internal static string GetUpdateScript <T>(Assembly assembly = null) { var database = Cfg.Databases[assembly ?? typeof(T).Assembly]; var dropPKConstraints = new StringBuilder(); var dropFKConstraints = new StringBuilder(); var dropColumns = new StringBuilder(); var dropTables = new StringBuilder(); var addTables = new StringBuilder(); var addManyToManyTables = new StringBuilder(); var addColumns = new StringBuilder(); var addConstraints = new StringBuilder(); var allCurrentDomainTypes = DwarfHelper.GetValidTypes <T>().ToList(); var currentManyToManyTables = GetCurrentManyToManyTables(allCurrentDomainTypes).Distinct().ToList(); var existingDatabaseTables = DwarfContext <T> .GetConfiguration().Database.ExecuteQuery("SELECT t.name FROM sys.tables t JOIN sys.schemas s ON s.schema_id = t.schema_id ").Select(x => x.name).ToList(); foreach (var existingTable in existingDatabaseTables.ToArray()) { if (!allCurrentDomainTypes.Select(x => x.Name).Any(x => x.Equals(existingTable)) && !currentManyToManyTables.Any(x => x.Equals(existingTable))) { DropDeadTableConstraints <T>(dropPKConstraints, dropFKConstraints, existingTable); dropTables.AppendLine("IF EXISTS (SELECT * FROM dbo.sysobjects WHERE Id = OBJECT_ID(N'[" + existingTable + "]') AND OBJECTPROPERTY(Id, N'IsUserTable') = 1) DROP Table [" + existingTable + "] "); existingDatabaseTables.Remove(existingTable); var constraints = DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("select CONSTRAINT_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '" + existingTable + "' "); foreach (var constraint in constraints) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + constraint.CONSTRAINT_NAME + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + existingTable + "]')) ALTER TABLE [" + existingTable + "] DROP CONSTRAINT [" + constraint.CONSTRAINT_NAME + "]"); } } } foreach (var type in allCurrentDomainTypes) { if (!existingDatabaseTables.Contains(type.Name)) { CreateTable <T>(addTables, type, addConstraints, addManyToManyTables); } foreach (var pi in DwarfHelper.GetManyToManyProperties(type)) { if (!existingDatabaseTables.Contains(ManyToManyAttribute.GetTableName(type, pi.ContainedProperty))) { CreateManyToManyTable(type, pi, addManyToManyTables, addConstraints); } } } foreach (var existingTable in existingDatabaseTables) { if (!allCurrentDomainTypes.Any(x => x.Name.Equals(existingTable))) { continue; } var existingColumns = (List <dynamic>) DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("SELECT c.name as name1, t.name as name2, c.max_length, c.is_nullable FROM sys.columns c inner join sys.types t on t.user_type_id = c.user_type_id WHERE object_id = OBJECT_ID('dbo." + existingTable + "') "); var type = allCurrentDomainTypes.First(x => x.Name.Equals(existingTable)); var props = DwarfHelper.GetGemListProperties(type).Union(DwarfHelper.GetDBProperties(type)).ToList(); foreach (var existingColumn in existingColumns) { string columnName = existingColumn.name1.ToString(); var pi = props.FirstOrDefault(x => x.Name.Equals(existingColumn.name2.ToString().Equals("uniqueidentifier") && !x.Name.Equals("Id") ? (columnName.EndsWith("Id") ? columnName.TruncateEnd(2) : columnName) : columnName)); if (pi == null) { dropColumns.AppendLine("IF EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'[" + existingTable + "]') AND Name = '" + columnName + "') ALTER TABLE dbo.[" + existingTable + "] DROP COLUMN " + columnName); if (existingColumn.name2.Equals("uniqueidentifier")) { var fkName = "FK_" + existingTable + "_" + columnName; AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + fkName + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + existingTable + "]')) ALTER TABLE [" + existingTable + "] DROP CONSTRAINT [" + fkName + "]"); } } } foreach (var pi in props) { if (DwarfPropertyAttribute.GetAttribute(pi.ContainedProperty) == null && !pi.PropertyType.Implements <IGemList>()) { continue; } var existingColumn = existingColumns.FirstOrDefault(x => (pi.PropertyType.Implements <IDwarf>() ? pi.Name + "Id" : pi.Name).Equals(x.name1)); if (existingColumn != null) { var typeChanged = !existingColumn.name2.Equals(TypeToColumnType(pi.ContainedProperty)); var lengthChanged = pi.PropertyType == typeof(string) && (existingColumn.name2.ToString().Equals(DwarfPropertyAttribute.GetAttribute(pi.ContainedProperty).UseMaxLength ? "-1" : "255")); var nullableChanged = (bool.Parse(existingColumn.is_nullable.ToString()) != IsColumnNullable(type, pi.ContainedProperty)); if (typeChanged | nullableChanged | lengthChanged) { addColumns.AppendLine("-- WARNING! TYPE CONVERSION MIGHT FAIL!!! "); addColumns.AppendLine("ALTER TABLE [" + type.Name + "] ALTER COLUMN " + TypeToColumnName(pi) + " " + TypeToColumnConstruction(type, pi.ContainedProperty, true).TruncateEnd(2)); addColumns.AppendLine("GO "); } if (pi.PropertyType.Implements <IDwarf>()) { var fkName = "FK_" + type.Name + "_" + pi.Name + "Id"; var constraintExists = DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("SELECT t.name FROM sys.objects obj inner join sys.foreign_key_columns fk on obj.object_id = fk.constraint_object_id inner join sys.columns c on fk.referenced_object_id = c.object_id and fk.referenced_column_id = c.column_id inner join sys.tables t on t.object_id = c.object_id inner join sys.tables t2 on fk.parent_object_id = t2.object_id WHERE obj.type = 'F' and t2.name = '" + type.Name + "' and obj.name = '" + fkName + "' and t.name = '" + pi.PropertyType.Name + "'"); if (!constraintExists.Any()) { dropColumns.AppendLine("IF EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'[" + existingTable + "]') AND Name = '" + existingColumn.name1 + "') ALTER TABLE dbo.[" + existingTable + "] DROP COLUMN " + existingColumn.name1); AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + fkName + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + existingTable + "]')) ALTER TABLE [" + existingTable + "] DROP CONSTRAINT [" + fkName + "]"); if (IsColumnNullable(type, pi.ContainedProperty)) { addColumns.AppendLine("ALTER TABLE [" + type.Name + "] ADD " + TypeToColumnName(pi) + " " + TypeToColumnConstruction(type, pi.ContainedProperty).TruncateEnd(2)); addColumns.AppendLine("GO "); } else { object value = null; try { value = Activator.CreateInstance(pi.PropertyType); } catch { } addColumns.AppendLine("GO "); addColumns.AppendLine("ALTER TABLE [" + type.Name + "] ADD " + TypeToColumnName(pi) + " " + TypeToColumnType(pi.ContainedProperty)); addColumns.AppendLine("GO "); addColumns.AppendLine("-- WARNING! Value is probably wrong. Correct before you execute! "); addColumns.AppendLine("UPDATE [" + type.Name + "] SET " + TypeToColumnName(pi) + " = " + database.ValueToSqlString(value) + " "); addColumns.AppendLine("GO "); addColumns.AppendLine("ALTER TABLE [" + type.Name + "] ALTER COLUMN " + TypeToColumnName(pi) + " " + TypeToColumnConstruction(type, pi.ContainedProperty, true).TruncateEnd(2)); addColumns.AppendLine("GO "); } var alterTable = "ALTER TABLE [" + type.Name + "] ADD CONSTRAINT [" + fkName + "] FOREIGN KEY (" + pi.Name + "Id) REFERENCES [" + pi.PropertyType.Name + "] (Id)"; if (!DwarfPropertyAttribute.GetAttribute(pi.ContainedProperty).DisableDeleteCascade) { alterTable += " ON DELETE CASCADE "; } addConstraints.AppendLine(alterTable); addConstraints.AppendLine("GO "); } } } else { if (IsColumnNullable(type, pi.ContainedProperty)) { addColumns.AppendLine("ALTER TABLE [" + type.Name + "] ADD " + TypeToColumnName(pi) + " " + TypeToColumnConstruction(type, pi.ContainedProperty).TruncateEnd(2)); addColumns.AppendLine("GO "); } else { object value = null; try { value = Activator.CreateInstance(pi.PropertyType); } catch { } addColumns.AppendLine("GO "); addColumns.AppendLine("ALTER TABLE [" + type.Name + "] ADD " + TypeToColumnName(pi) + " " + " " + TypeToColumnConstruction(type, pi.ContainedProperty).TruncateEnd(2).Replace("NOT NULL", string.Empty)); addColumns.AppendLine("GO "); addColumns.AppendLine("-- WARNING! Value is probably wrong. Correct before you execute! "); addColumns.AppendLine("UPDATE [" + type.Name + "] SET " + TypeToColumnName(pi) + " = " + database.ValueToSqlString(value) + " "); addColumns.AppendLine("GO "); addColumns.AppendLine("ALTER TABLE [" + type.Name + "] ALTER COLUMN " + TypeToColumnName(pi) + " " + TypeToColumnConstruction(type, pi.ContainedProperty, true).TruncateEnd(2)); addColumns.AppendLine("GO "); } if (pi.PropertyType.Implements <IDwarf>()) { var constraintName = "FK_" + type.Name + "_" + pi.Name; var alterTable = "ALTER TABLE [" + type.Name + "] ADD CONSTRAINT [" + constraintName + "Id] FOREIGN KEY (" + pi.Name + "Id) REFERENCES [" + pi.PropertyType.Name + "] (Id)"; if (!DwarfPropertyAttribute.GetAttribute(pi.ContainedProperty).DisableDeleteCascade) { alterTable += " ON DELETE CASCADE "; } addConstraints.AppendLine(alterTable); addColumns.AppendLine("GO "); } } } } foreach (var existingTable in existingDatabaseTables) { var uqConstraints = ((List <dynamic>)DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("SELECT obj.name FROM sys.objects obj inner join sys.tables t on obj.parent_object_id = t.object_id WHERE obj.type = 'UQ' and t.name = '" + existingTable + "'")).Select(x => x.name); foreach (var uqConstraint in uqConstraints) { var uqParts = uqConstraint.Split('_'); var type = allCurrentDomainTypes.FirstOrDefault(x => x.Name.Equals(uqParts[1])); if (type != null) { var columns = (List <dynamic>) DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("select COLUMN_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where CONSTRAINT_NAME = '" + uqConstraint + "'"); //Not a unique combination, but a unique column (right?) if (columns.Count == 1) { var pi = ColumnToProperty(type, columns.First().COLUMN_NAME); if (pi != null) { var att = DwarfPropertyAttribute.GetAttribute(pi); if (att != null && !att.IsUnique) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + uqConstraint + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + uqConstraint + "]"); } } } else { var uqProperties = (IEnumerable <ExpressionProperty>)DwarfHelper.GetUniqueGroupProperties <T>(type, uqParts[2]); if (!uqProperties.Any()) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + uqConstraint + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + uqConstraint + "]"); } else { var difference = uqProperties.Select(x => x.Name).Except(columns.Select(x => x.COLUMN_NAME)); if (difference.Any()) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + uqConstraint + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + uqConstraint + "]"); CreateUniqueConstraint <T>(addConstraints, type); } } } } } } foreach (var type in allCurrentDomainTypes) { foreach (var pi in DwarfHelper.GetUniqueDBProperties <T>(type)) { var piName = pi.Name + (pi.PropertyType.Implements <IDwarf>() ? "Id" : string.Empty); var uqName = "UQ_" + type.Name + "_" + piName; var columns = DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("select COLUMN_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where CONSTRAINT_NAME = '" + uqName + "'"); if (columns.Count == 0 && !addColumns.ToString().Contains(uqName) && !addTables.ToString().Contains(uqName)) { addConstraints.AppendLine("ALTER TABLE [" + type.Name + "] ADD CONSTRAINT [" + uqName + "] UNIQUE ([" + pi.Name + "]) "); addConstraints.AppendLine("GO "); } } foreach (var uniqueGroupName in DwarfHelper.GetUniqueGroupNames <T>(type)) { var pis = DwarfHelper.GetUniqueGroupProperties <T>(type, uniqueGroupName); var columns = DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("select COLUMN_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where CONSTRAINT_NAME = 'UQ_" + type.Name + "_" + uniqueGroupName + "'").Select(x => x.COLUMN_NAME).ToList(); if (columns.Any()) { var differnce = pis.Select(x => x.Name).Except(columns); if (differnce.Any()) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + uniqueGroupName + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + uniqueGroupName + "]"); CreateUniqueConstraint <T>(addConstraints, type, uniqueGroupName); addConstraints.AppendLine("GO "); } } else { CreateUniqueConstraint <T>(addConstraints, type, uniqueGroupName); addConstraints.AppendLine("GO "); } } var uniqueColumns = DwarfContext <T> .GetDatabase().ExecuteCustomQuery <T>("select COLUMN_NAME, CONSTRAINT_NAME from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where CONSTRAINT_NAME like 'UQ_%' and CONSTRAINT_NAME like '%_' + COLUMN_NAME and TABLE_NAME = '" + type.Name + "' "); foreach (var uniqueColumn in uniqueColumns) { var pi = ColumnToProperty(type, uniqueColumn.COLUMN_NAME.ToString()); if (pi == null) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + uniqueColumn.CONSTRAINT_NAME + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + uniqueColumn.CONSTRAINT_NAME + "]"); continue; } var att = DwarfPropertyAttribute.GetAttribute(pi); if (att == null) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + uniqueColumn.CONSTRAINT_NAME + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + uniqueColumn.CONSTRAINT_NAME + "]"); continue; } if (!att.IsUnique) { AddDropConstraint(dropPKConstraints, dropFKConstraints, "IF EXISTS (SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[" + uniqueColumn.CONSTRAINT_NAME + "]') AND PARENT_OBJECT_ID = OBJECT_ID('[" + type.Name + "]')) ALTER TABLE [" + type.Name + "] DROP CONSTRAINT [" + uniqueColumn.CONSTRAINT_NAME + "]"); } } } var result = AppendSection(dropFKConstraints) + AppendSection(dropPKConstraints) + AppendSection(dropColumns) + AppendSection(dropTables) + AppendSection(addTables) + AppendSection(addManyToManyTables) + AppendSection(addColumns) + AppendSection(addConstraints); if (!string.IsNullOrEmpty(result.Trim())) { return("--WARNING--\r\n" + "--Use these scripts with caution as there's no guarantee that all model changes are --\r\n" + "--reflected here nor that any previously persisted data will remain intact post execution. --\r\n" + "\r\n" + result); } return(string.Empty); }
/// <summary> /// Returns the ManyToMany table name for the supplied criteria /// </summary> public static string GetTableName <T>(Expression <Func <T, object> > exp) { var pi = PropertyHelper.GetProperty(DwarfHelper.DeProxyfy(typeof(T)), ReflectionHelper.GetPropertyName(exp)); return(GetTableName(typeof(T), pi.ContainedProperty)); }
protected override ulong GetLayoutHeaderSize() { // 3. debug_abbrev_offset (section offset) // 4. address_size (ubyte) return(DwarfHelper.SizeOfUInt(Is64BitEncoding) + 1); }
/// <summary> /// Converts an SqlDataReader row into an object of the type T /// </summary> protected T TupleToObject <T>(DbDataReader sdr) where T : Dwarf <T>, new() { var type = typeof(T); var obj = DwarfHelper.CreateInstance <T>(); for (var i = 0; i < sdr.FieldCount; i++) { var propertyName = sdr.GetName(i); var propertyValue = sdr.GetValue(i); var pi = PropertyHelper.GetProperty(type, propertyName) ?? PropertyHelper.GetProperty(type, propertyName.Replace("Id", string.Empty)); if (pi == null) { continue; } if (propertyValue is DBNull) { propertyValue = pi.ContainedProperty.PropertyType == typeof(string) ? string.Empty : null; } else if (pi.PropertyType.Implements <IGem>()) { propertyValue = Cfg.LoadGem[pi.PropertyType](propertyValue.ToString()); } else if (pi.PropertyType.IsEnum() && propertyValue != null) { propertyValue = Enum.Parse(pi.PropertyType.GetTrueEnumType(), propertyValue.ToString()); } else if (pi.PropertyType.Implements <Type>()) { propertyValue = typeof(T).Assembly.GetType(propertyValue.ToString()); } else if (pi.PropertyType.Implements <IDwarf>()) { var att = DwarfPropertyAttribute.GetAttribute(pi.ContainedProperty); if (att != null) { if (DwarfPropertyAttribute.IsFK(pi)) { obj.SetOriginalValue(pi.Name, propertyValue); if (att.EagerLoad) { var targetType = pi.PropertyType; if (propertyValue != null) { PropertyHelper.SetValue(obj, pi.Name, Cfg.LoadExpressions[targetType]((Guid)propertyValue)); } } continue; } } } if (pi.PropertyType == typeof(string) && propertyValue != null) { propertyValue = propertyValue.ToString().Replace("\\r\\n", "\r\n"); } PropertyHelper.SetValue(obj, pi.Name, propertyValue); obj.SetOriginalValue(pi.Name, propertyValue); } obj.IsSaved = true; return(obj); }