Skip to content

Scoped table aliases to session factory configuration #1517

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/teamcity/oracle/oracle_installation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,10 @@ This is needed because NHibernate test uses the managed driver NuGet package, bu
version needs to be removed from the GAC. Read more on https://stackoverflow.com/a/35176586/1178314.
Not doing this may notably cause failures in distributed transaction tests.

Adjust the connection string for the tests:
The tests involve creating and dropping many tables, sometimes with the same names but different data
types. This does not play well with Oracle meta data pooling, which needs to be disabled.
Add into your ODP.NET connection string:
Metadata Pooling=false;Self Tuning=false;

Please note that some tests are dependent on the machine locales, and may fail if they are not English.
2 changes: 1 addition & 1 deletion src/NHibernate.Test/MappingTest/ColumnFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void GetAliasWithTableSuffixRespectsMaxAliasLength(string columnName)
// Test case is meant for a max length of 10, adjusts name if it is more.
columnName = AdjustColumnNameToMaxLength(columnName, dialect, 10);

var table = new Table();
var table = new Table() {UniqueInteger = 1};
var column = new Column(columnName);

string generatedAlias = column.GetAlias(dialect, table);
Expand Down
42 changes: 1 addition & 41 deletions src/NHibernate.Test/MappingTest/TableFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,45 +61,5 @@ public void SchemaNameQuoted()

Assert.AreEqual("[schema].name", tbl.GetQualifiedName(dialect));
}

[Test]
public void TablesUniquelyNamed()
{
Table tbl1 = new Table();
Table tbl2 = new Table();

Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
}

[Test]
public void TablesUniquelyNamedOnlyWithinThread()
{
var uniqueIntegerList = new System.Collections.Concurrent.ConcurrentBag<int>();
var method = new ThreadStart(() =>
{
Table tbl1 = new Table();
Table tbl2 = new Table();

// Store these values for later comparison
uniqueIntegerList.Add(tbl1.UniqueInteger);
uniqueIntegerList.Add(tbl2.UniqueInteger);

// Ensure that within a thread we have unique integers
Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
});

var thread1 = new CrossThreadTestRunner(method);
var thread2 = new CrossThreadTestRunner(method);

thread1.Start();
thread2.Start();

thread1.Join();
thread2.Join();

// There should in total be 4 tables, but only two distinct identifiers.
Assert.AreEqual(4, uniqueIntegerList.Count);
Assert.AreEqual(2, uniqueIntegerList.Distinct().Count());
}
}
}
}
7 changes: 5 additions & 2 deletions src/NHibernate/Cfg/Mappings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ public Table AddTable(string schema, string catalog, string name, string subsele
table.Catalog = catalog;
table.Subselect = subselect;
table.SchemaActions = GetSchemaActions(schemaAction);
table.UniqueInteger = tables.Count;
tables[key] = table;
}
else
Expand Down Expand Up @@ -337,15 +338,17 @@ public Table AddDenormalizedTable(string schema, string catalog, string name, bo
Subselect = subselect
};

Table existing;
if (tables.TryGetValue(key, out existing))
var tableIndex = tables.Count;
if (tables.TryGetValue(key, out var existing))
{
if (existing.IsPhysicalTable)
{
throw new DuplicateMappingException("table", name);
}
tableIndex = existing.UniqueInteger;
}

table.UniqueInteger = tableIndex;
tables[key] = table;
return table;
}
Expand Down
10 changes: 4 additions & 6 deletions src/NHibernate/Mapping/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,11 @@ public enum SchemaAction
[Serializable]
public class Table : IRelationalModel
{
[ThreadStatic]
private static int tableCounter;

private readonly List<string> checkConstraints = new List<string>();
private readonly LinkedHashMap<string, Column> columns = new LinkedHashMap<string, Column>();
private readonly Dictionary<ForeignKeyKey, ForeignKey> foreignKeys = new Dictionary<ForeignKeyKey, ForeignKey>();
private readonly Dictionary<string, Index> indexes = new Dictionary<string, Index>();
private readonly int uniqueInteger;
private int? uniqueInteger;
private readonly Dictionary<string, UniqueKey> uniqueKeys = new Dictionary<string, UniqueKey>();
private string catalog;
private string comment;
Expand All @@ -52,7 +49,6 @@ public class Table : IRelationalModel
/// </summary>
public Table()
{
uniqueInteger = tableCounter++;
}

public Table(string name) : this()
Expand Down Expand Up @@ -189,11 +185,13 @@ public string Schema

/// <summary>
/// Gets the unique number of the Table.
/// Used for SQL alias generation
/// </summary>
/// <value>The unique number of the Table.</value>
public int UniqueInteger
{
get { return uniqueInteger; }
get { return uniqueInteger ?? throw new InvalidOperationException(nameof(UniqueInteger) + " has not been supplied"); }
set { uniqueInteger = value; }
}

/// <summary>
Expand Down
8 changes: 4 additions & 4 deletions teamcity.build
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
<target name="setup-teamcity-oracle32">
<property name="nhibernate.connection.driver_class" value="NHibernate.Driver.OracleDataClientDriver" />
<property name="nhibernate.dialect" value="NHibernate.Dialect.Oracle10gDialect" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Metadata Pooling=false;Self Tuning=false;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
Copy link
Member

@fredericDelaporte fredericDelaporte Jan 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good finding with these parameters, it works way better than clearing the pool. Can you please update lib\teamcity\oracle\oracle_installation.txt too? It should tell about these parameters for helping developers having the tests pass on their box. (But it cannot be put in the config template, since this one is also distributed with NHibernate as a config sample, and that disabling these parameters makes sens only for the tests, not for a normal application.)

Something like the following could be added toward the end of oracle_installation.txt, just above its last line I think:

Adjust the connection string for the tests:
The tests involve creating and dropping many tables, sometimes with the same names but different data
types. This does not play well with Oracle meta data pooling, which needs to be disabled.
Add into your ODP.NET connection string:
Metadata Pooling=false;Self Tuning=false;

<!-- Teamcity Oracle test database is configured with a non-Unicode encoding -->
<property name="nhibernate.oracle.use_n_prefixed_types_for_unicode" value="true" />
<copy todir="${bin.dir}">
Expand All @@ -140,7 +140,7 @@
<property name="nunit-x64" value="true" />
<property name="nhibernate.connection.driver_class" value="NHibernate.Driver.OracleDataClientDriver" />
<property name="nhibernate.dialect" value="NHibernate.Dialect.Oracle10gDialect" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Metadata Pooling=false;Self Tuning=false;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
<!-- Teamcity Oracle test database is configured with a non-Unicode encoding -->
<property name="nhibernate.oracle.use_n_prefixed_types_for_unicode" value="true" />
<copy todir="${bin.dir}">
Expand All @@ -155,7 +155,7 @@
<target name="setup-teamcity-oracle-managed32">
<property name="nhibernate.connection.driver_class" value="NHibernate.Driver.OracleManagedDataClientDriver" />
<property name="nhibernate.dialect" value="NHibernate.Dialect.Oracle10gDialect" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Metadata Pooling=false;Self Tuning=false;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
<!-- Teamcity Oracle test database is configured with a non-Unicode encoding -->
<property name="nhibernate.oracle.use_n_prefixed_types_for_unicode" value="true" />
</target>
Expand All @@ -164,7 +164,7 @@
<property name="nunit-x64" value="true" />
<property name="nhibernate.connection.driver_class" value="NHibernate.Driver.OracleManagedDataClientDriver" />
<property name="nhibernate.dialect" value="NHibernate.Dialect.Oracle10gDialect" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Metadata Pooling=false;Self Tuning=false;Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))" />
<!-- Teamcity Oracle test database is configured with a non-Unicode encoding -->
<property name="nhibernate.oracle.use_n_prefixed_types_for_unicode" value="true" />
</target>
Expand Down