-
Notifications
You must be signed in to change notification settings - Fork 934
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather:
- Keep
uniqueInteger
readonly. - Add a constructor taking
uniqueInteger
as an argument. - Obsolete the parameter-less constructor.
- Remove
tableCounter
. - Cease calling the parameter-less constructor from the constructor taking a table name. This constructor is only used in cases which do not need
UniqueInteger
. - Expose the Configuration.tables count as an internal property.
- Use it as the base of temporary table indexes in the session factory constructor. At that point, all tables the session factory will use have been added to the
Configuration
, so there will be no index collision between temporary tables and other tables used by the session factory.
It was my first thought. But it's not very convenient to supply index beforehand. Plus this constructor now needs to be also exposed in DenormalizedTable. That's why I made this "shortcut". Though if you think it's a right way to do it - I will do it.
Wouldn't it be a breaking change? It's a public class and that changes behaviour of default constructor. It seems it's better to keep tableCounter and keep incrementing it to make obsolete constructor behaviour intact and remove it later along with ctor. |
Removing a private member is not a breaking change. Changing the uniqueness of values of a public property is a gray area, but this PR anyway already does this, since previously any new
There are only three cases where this index is used in NHibernate.csproj: I do not see any difficulties neither for The third case will require more work, adding a new overload to The other usages of
Yes, indeed, and the previous one obsoleted too. But that is a small inconvenience I think, allowing to have a consistent There are also many testes in NHibernate.Test.csproj which will be impacted. I have not checked them, but I except them to either not really need that counter, or to be obsoleted by the way we change the counter logic, or to be not hard to fix for supplying a counter valid for the test. |
I'm looking into nhibernate-core/src/NHibernate/Mapping/PersistentClass.cs Lines 1121 to 1134 in d372ee3
And from what I see aliases here are irrelevant. Table class is not saved anywhere and only two strings are saved: create table #[TableName] ([PrimaryKeyID] INT not null) So aliases are also not needed. So it seems we don't really need to do anything for temp tables. |
Indeed, I have forgotten to thoroughly check this case. So there, why not using the constructor with table name overload, and forget about the index? It should be the simplest way to do the change. |
@fredericDelaporte Some strange exceptions from Oracle. Don't you happen to know that it's something that might be not related to my changes? ) |
I have seen them, but I do not see how they could relate to changes here. I can relaunch the build to check if they occur again. Or if you change this PR implementation, we can just wait for the new builds which will be run. Update: they do not occur on another PR, so either this was a temporary trouble, or the changes in this PR cause issues to Oracle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It really looks like changing this counter causes issues to Oracle. Now we have to find out why.
src/NHibernate/Mapping/Table.cs
Outdated
@@ -194,6 +190,7 @@ public string Schema | |||
public int UniqueInteger | |||
{ | |||
get { return uniqueInteger; } | |||
internal set { uniqueInteger = value; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this member now depends on being externally supplied (be it by setter or constructor), maybe should we guard against it being used without having been set.
I would do it by switching the backing field to nullable then adjusting the getter to something like get => uniqueInteger ?? throw new InvalidOperation("UniqueInteger has not been supplied");
. (If using expression bodied getter, change also the setter for consistency.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fredericDelaporte Good idea. Will do it. And before making any changes in ctor... Are you sure about it? ) I see no troubles with this change but I just don't see why to fight to keep uniqueInteger
readonly. Considering that it's the only read-only field in this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forget about the constructor. I mentioned it just to tell that if this member value was supplied through a constructor, I would still consider doing this check in the getter.
Yep. What's more interesting - from what I see exception is thrown not from test. It's thrown from test clean up code: |
Running NH-1362 test in isolation succeeds. Running it along with NH-1301 test fails. It looks like Oracle caches returned types for a query then fails re-running the same query when the underlying table definition has changed. Clearing the connection pool avoids the trouble. So we have to use a trick similar to the one put in place for Firebird, see Update: |
5721fd0
to
7694de0
Compare
src/NHibernate.Test/TestCase.cs
Outdated
// So exception can be thrown if two tests execute same query but with different types in result (like for Entity.Id int and Entity.Id Guid) | ||
if (Dialect is Oracle8iDialect) | ||
{ | ||
OracleConnection.ClearAllPools(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will work only if the Oracle driver is the managed one. But two other Oracle drivers are usable. (Currently their specific TeamCity builds are not enabled.)
I have made a PR on your branch for handling them all: bahusoid#1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I've adjusted it per @hazzik comments
Now it succeeds but the Oracle build time seems to have raised from twenty minutes to fifty... It is too near to the one hour timeout. For checking it twice, I have relaunched another Oracle build for the latest commit of this PR. If it takes fifty minutes again, we will have to devise another solution.
Or other idea? |
The second Oracle run has taken fifty minutes again, we need another solution. |
070d735
to
cedaecb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your last solution works great, 21 minutes. Now previous attempts need to be cleaned-up, and some guidance should be added for developer willing to run the tests locally. See review comments.
src/NHibernate.Test/TestCase.cs
Outdated
@@ -14,6 +14,8 @@ | |||
using NUnit.Framework.Interfaces; | |||
using System.Text; | |||
using NHibernate.Driver; | |||
using NHibernate.SqlCommand; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes to this file should be reverted, since they were done for the "clear pool" solution.
src/NHibernate.sln.DotSettings
Outdated
@@ -1,13 +1,16 @@ | |||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | |||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CommonFormatter/ALIGNMENT_TAB_FILL_STYLE/@EntryValue">USE_SPACES</s:String> | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better revert the DotSettings update for now. The alignement tab fill style seems removed while we had explicitly set it.
@@ -1,9 +1,7 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Data; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes to this file should be reverted, since they were done for the "clear pool" solution.
@@ -59,5 +59,17 @@ protected override void OnBeforePrepare(DbCommand command) | |||
" does not support CallableStatement syntax (stored procedures)." + | |||
" Consider using OracleDataClientDriver instead."); | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes to this file should be reverted, since they were done for the "clear pool" solution.
@@ -2,7 +2,6 @@ | |||
using System.Collections.Generic; | |||
using System.Data; | |||
using System.Data.Common; | |||
using System.Reflection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes to this file should be reverted, since they were done for the "clear pool" solution.
@@ -70,5 +72,69 @@ public override DbCommand CreateCommand() | |||
{ | |||
return connectionCommandProvider.CreateCommand(); | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes to this file should be reverted, since they were done for the "clear pool" solution.
@@ -1123,8 +1123,7 @@ public void PrepareTemporaryTables(IMapping mapping, Dialect.Dialect dialect) | |||
if (dialect.SupportsTemporaryTables) | |||
{ | |||
temporaryIdTableName = dialect.GenerateTemporaryTableName(Table.Name); | |||
Table table = new Table(); | |||
table.Name = temporaryIdTableName; | |||
Table table = new Table(temporaryIdTableName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is not necessary, since the parameter-less constructor is not obsoleted for one taking the counter.
teamcity.build
Outdated
@@ -116,15 +116,15 @@ | |||
<target name="setup-teamcity-oracle"> | |||
<property name="nhibernate.connection.driver_class" value="NHibernate.Driver.OracleClientDriver" /> | |||
<property name="nhibernate.dialect" value="NHibernate.Dialect.Oracle10gDialect" /> | |||
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Data Source=XE" /> | |||
<property name="nhibernate.connection.connection_string" value="User ID=nhibernate;Password=nhibernate;Data Source=XE;Metadata Pooling=false;Self Tuning=false;" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These parameters are ODP.NET specific, they are not supported by System.Data.Oracle
(which is used by OracleClientDriver
). Do not add them to this build. Anyway System.Data.Oracle
is obsolete since long and it is unlikely we will test it some day again.
<property name="NHibernate.Test.IgnoreFail" value="true" /> | ||
<property name="teamcity.last.result" value="${root.dir}/lib/teamcity/oracle/NHibernate.Test.last-results.xml" /> | ||
</target> | ||
|
||
<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)))" /> |
There was a problem hiding this comment.
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;
I have pushed the cleanup and my suggestion about Oracle instructions. |
Thanks for you changes. I've just come back to start working on your comments :) |
I see there is still some leftovers like (dotSettings file). I will handle it |
I got trapped by the "end of file normalization" due to editor setting. You will need to revert the end file last line with an editor which does not honor |
@fredericDelaporte Done |
What do you mean by this? Have you some additional changes to do here, or can this be merged? |
@fredericDelaporte This PR is ready. I meant play with interning aliases and related stuff. It's all about another PR #1503 where I made this comment in response to #1503 (comment). |
Make table aliases generated for same mapping but from different session factories the same:
To make sure that the same queries are executed for the same database from different apps (I described this scenario here)
To allow further code improvements (we can for instance start interning aliases/pre-generated queries for entities, as this data now should be the same for same mapping)
Fixes Table counter for aliases should be stable #1417.
Though tableCounter is still rise endlessly - but its value is not used for mapped tables stored inConfiguration.tables
.It turns out that tableCounter is not really needed outside configuration (created table classes don't use UniqueInteger) - so it's been removed.