Last active
May 24, 2016 20:49
-
-
Save qrdemole/d86da2616d669a3cdc5ba34f4acb7020 to your computer and use it in GitHub Desktop.
Slightly modified NHibernate's SchemaValidator for better usage in an integration test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Data.Common; | |
using NHibernate; | |
using NHibernate.Cfg; | |
using NHibernate.Dialect; | |
using NHibernate.Dialect.Schema; | |
using NHibernate.Engine; | |
using NHibernate.Id; | |
using NHibernate.Mapping; | |
using NHibernate.Tool.hbm2ddl; | |
using NHibernate.Util; | |
namespace TestInfrastructure | |
{ | |
public class SchemaValidator | |
{ | |
private readonly Configuration configuration; | |
private readonly IConnectionHelper connectionHelper; | |
private readonly Dialect dialect; | |
public SchemaValidator(Configuration cfg) : this(cfg, cfg.Properties) { } | |
public SchemaValidator(Configuration cfg, IDictionary<string, string> connectionProperties) | |
{ | |
configuration = cfg; | |
dialect = Dialect.GetDialect(connectionProperties); | |
IDictionary<string, string> props = new Dictionary<string, string>(dialect.DefaultProperties); | |
foreach (var prop in connectionProperties) | |
{ | |
props[prop.Key] = prop.Value; | |
} | |
connectionHelper = new ManagedProviderConnectionHelper(props); | |
} | |
public SchemaValidator(Configuration cfg, Settings settings) | |
{ | |
configuration = cfg; | |
dialect = settings.Dialect; | |
connectionHelper = new SuppliedConnectionProviderConnectionHelper(settings.ConnectionProvider); | |
} | |
public IList<string> Validate() | |
{ | |
try | |
{ | |
DatabaseMetadata meta; | |
connectionHelper.Prepare(); | |
DbConnection connection = connectionHelper.Connection; | |
meta = new DatabaseMetadata(connection, dialect, false); | |
return ValidateSchema(dialect, meta); | |
} | |
finally | |
{ | |
try | |
{ | |
connectionHelper.Release(); | |
} | |
catch (Exception) | |
{ | |
// ignored | |
} | |
} | |
} | |
private IList<string> ValidateSchema( | |
Dialect dialect, DatabaseMetadata databaseMetadata) | |
{ | |
IList<string> problems = new List<string>(); | |
string defaultCatalog = PropertiesHelper.GetString(NHibernate.Cfg.Environment.DefaultCatalog, | |
configuration.Properties, null); | |
string defaultSchema = PropertiesHelper.GetString(NHibernate.Cfg.Environment.DefaultSchema, | |
configuration.Properties, null); | |
IMapping mapping = configuration.BuildMapping(); | |
ICollection<PersistentClass> list = configuration.ClassMappings; | |
foreach (PersistentClass pc in list) | |
{ | |
try | |
{ | |
var table = pc.Table; | |
if (table.IsPhysicalTable) | |
{ | |
ITableMetadata tableInfo = databaseMetadata.GetTableMetadata( | |
UnQuote(table.Name), | |
table.Schema ?? defaultSchema, | |
table.Catalog ?? defaultCatalog, | |
table.IsQuoted); | |
if (tableInfo == null) | |
problems.Add(string.Format("Missing table: {0}", table.Name)); | |
else | |
ValidateColumns(problems, table, dialect, mapping, tableInfo); | |
} | |
} | |
catch (HibernateException ex) | |
{ | |
problems.Add(ex.Message); | |
} | |
} | |
var persistenceIdentifierGenerators = IterateGenerators(dialect); | |
foreach (var generator in persistenceIdentifierGenerators) | |
{ | |
string key = generator.GeneratorKey(); | |
if (!databaseMetadata.IsSequence(key) && !databaseMetadata.IsTable(key)) | |
{ | |
problems.Add(string.Format("Missing sequence or table: {0}", key)); | |
} | |
} | |
return problems; | |
} | |
private string UnQuote(string name) | |
{ | |
return name.TrimStart('[').TrimEnd(']'); | |
} | |
private IEnumerable<IPersistentIdentifierGenerator> IterateGenerators(Dialect dialect) | |
{ | |
var generators = new Dictionary<string, IPersistentIdentifierGenerator>(); | |
string defaultCatalog = PropertiesHelper.GetString(NHibernate.Cfg.Environment.DefaultCatalog, | |
configuration.Properties, null); | |
string defaultSchema = PropertiesHelper.GetString(NHibernate.Cfg.Environment.DefaultSchema, | |
configuration.Properties, null); | |
foreach (var pc in configuration.ClassMappings) | |
{ | |
if (!pc.IsInherited) | |
{ | |
var ig = | |
pc.Identifier.CreateIdentifierGenerator(dialect, defaultCatalog, defaultSchema, (RootClass)pc) as | |
IPersistentIdentifierGenerator; | |
if (ig != null) | |
{ | |
generators[ig.GeneratorKey()] = ig; | |
} | |
} | |
} | |
foreach (var collection in configuration.CollectionMappings) | |
{ | |
if (collection.IsIdentified) | |
{ | |
var ig = | |
((IdentifierCollection)collection).Identifier.CreateIdentifierGenerator(dialect, defaultCatalog, defaultSchema, | |
null) as IPersistentIdentifierGenerator; | |
if (ig != null) | |
{ | |
generators[ig.GeneratorKey()] = ig; | |
} | |
} | |
} | |
return generators.Values; | |
} | |
private void ValidateColumns( | |
IList<string> problems, | |
Table table, | |
Dialect dialect, | |
IMapping mapping, | |
ITableMetadata tableInfo) | |
{ | |
IEnumerable<Column> iter = table.ColumnIterator; | |
foreach (Column column in iter) | |
{ | |
IColumnMetadata columnInfo = tableInfo.GetColumnMetadata(column.Name); | |
if (columnInfo == null) | |
{ | |
problems.Add(string.Format("Missing column: {0} in {1}", column.Name, | |
dialect.Qualify(tableInfo.Catalog, tableInfo.Schema, tableInfo.Name))); | |
} | |
else | |
{ | |
bool typesMatch = column.GetSqlType(dialect, mapping).ToLower().StartsWith(columnInfo.TypeName.ToLower()); | |
if (!typesMatch) | |
{ | |
problems.Add(string.Format("Wrong column type in {0} for column {1}. Found: {2}, Expected {3}", | |
dialect.Qualify(tableInfo.Catalog, tableInfo.Schema, tableInfo.Name), | |
column.Name, columnInfo.TypeName.ToLower(), | |
column.GetSqlType(dialect, mapping))); | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment