Hello,
This is my first post here. I'm working in a web application using the MonoRail framework. I'm using the SVN version of MonoRail so the NHibernate version it uses is 1.2. After asking my problem in MonoRail forum (
http://forum.castleproject.org/viewtopic.php?t=3270) they suggested me that it is a NHibernate problem, so here I am. Now the problem:
We are developing a custom TimeZone class with DayLight Saving rules. Following the example at
http://www.castleproject.org/activerecord/documentation/trunk/usersguide/relations/hasandbelongs.html
we have these models:
Code:
[ActiveRecord(Table = "vt_timezones", Schema = "dbo")]
public class CustomTimeZone : ActiveRecordBase
{
int _Id;
string _Continent;
string _ZoneName;
int _UtcOffset;
string _RuleName;
private IList dstrules = new ArrayList();
static public string NoRuleName = "-";
public CustomTimeZone()
{
_Continent = string.Empty;
_ZoneName = string.Empty;
_UtcOffset = 0;
_RuleName = string.Empty;
}
#region Campos de la tabla
[PrimaryKey(PrimaryKeyType.Native, "id")]
public int Id
{
get { return _Id; }
set { _Id = value; }
}
[Property(Column = "continent", Length = 50, NotNull = true)]
public string Continent
{
get { return _Continent; }
set { _Continent = value; }
}
[Property(Column = "zonename", Length = 250, NotNull = true)]
public string ZoneName
{
get { return _ZoneName; }
set { _ZoneName = value; }
}
[Property(Column = "utcoffset", NotNull = true)]
public int UtcOffset
{
get { return _UtcOffset; }
set { _UtcOffset = value; }
}
[Property(Column = "rulename", Length = 50, NotNull = true)]
public string RuleName
{
get { return _RuleName; }
set { _RuleName = value; }
}
[HasAndBelongsToMany(typeof(DSTRule),
Table = "vt_timezones_dstrules", ColumnKey = "timezoneid", ColumnRef = "dstruleid")]
public IList Rules
{
get { return dstrules; }
set { dstrules = value; }
}
#endregion
}
Code:
[ActiveRecord(Table = "vt_dstrules", Schema = "dbo")]
public class DSTRule : ActiveRecordBase
{
int _Id;
string _RuleName;
int _FromYear;
int _ToYear;
int _StartMonth; //January = 1 ... December = 12
int _StartDay;
int _StartDay_DayOfWeek; //Sunday = 0, Monday = 1 ... (System.DayOfWeek)
int _StartTime;
int _SaveTime;
private IList timezones = new ArrayList();
public enum WeekDay
{
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7
}
public enum Month
{
January = 1,
February = 2,
March = 3,
April = 4,
May = 5,
June = 6,
July = 7,
August = 8,
September = 9,
October = 10,
November = 11,
December = 12
}
#region Campos de la tabla
[PrimaryKey(PrimaryKeyType.Native, "id")]
public int Id
{
get { return _Id; }
set { _Id = value; }
}
[Property(Column = "rulename", Length = 50, NotNull = true)]
public string RuleName
{
get { return _RuleName; }
set { _RuleName = value; }
}
[Property(Column = "fromyear", NotNull = true)]
public int FromYear
{
get { return _FromYear; }
set { _FromYear = value; }
}
[Property(Column = "toyear", NotNull = true)]
public int ToYear
{
get { return _ToYear; }
set { _ToYear = value; }
}
[Property(Column = "startmonth", NotNull = true)]
public int StartMonth
{
get { return _StartMonth; }
set { _StartMonth = value; }
}
[Property(Column = "startday", NotNull = true)]
public int StartDay
{
get { return _StartDay; }
set { _StartDay = value; }
}
[Property(Column = "startday_dayofweek", NotNull = true)]
public int StartDay_DayOfWeek
{
get { return _StartDay_DayOfWeek; }
set { _StartDay_DayOfWeek = value; }
}
[Property(Column = "starttime", NotNull = true)]
public int StartTime
{
get { return _StartTime; }
set { _StartTime = value; }
}
[Property(Column = "savetime", NotNull = true)]
public int SaveTime
{
get { return _SaveTime; }
set { _SaveTime = value; }
}
[HasAndBelongsToMany(typeof(CustomTimeZone),
Table = "vt_timezones_dstrules", ColumnKey = "dstruleid",
ColumnRef = "timezoneid", Inverse = true)]
public IList TimeZones
{
get { return timezones; }
set { timezones = value; }
}
#endregion
}
And the relation:
Code:
[ActiveRecord(Table = "vt_timezones_dstrules", Schema = "dbo")]
public class CustomTimeZoneDSTRule : ActiveRecordBase
{
int _Id;
CustomTimeZone _timezoneid;
DSTRule _dstruleid;
#region Campos de la tabla
[PrimaryKey(PrimaryKeyType.Native, "id")]
public int Id
{
get { return _Id; }
set { _Id = value; }
}
[BelongsTo("timezoneid")]
public CustomTimeZone TimeZone
{
get { return _timezoneid; }
set { _timezoneid = value; }
}
[BelongsTo("dstruleid")]
public DSTRule DSTRule
{
get { return _dstruleid; }
set { _dstruleid = value; }
}
#endregion
}
If the tables are created directly on SQL Server it works fine, but if I use
ActiveRecordStarter.CreateSchema(); I get the following exception:
Code:
Ya hay un objeto con el nombre 'vt_timezones_dstrules' en la base de datos.
Descripción: Excepción no controlada al ejecutar la solicitud Web actual. Revise el seguimiento de la pila para obtener más información acerca del error y dónde se originó en el código.
Detalles de la excepción: System.Data.SqlClient.SqlException: Ya hay un objeto con el nombre 'vt_timezones_dstrules' en la base de datos.
Error de código fuente:
Línea 40: // la siguiente sección. Una vez creado el esquema volveremos a comentarla.
Línea 41:
Línea 42: ActiveRecordStarter.CreateSchema();
Línea 43: InitDataBase();
Línea 44:
Archivo de origen: D:\Documents\Visual Studio 2005\Projects\VirtualTutor\VirtualTutor\GlobalApplication.cs Línea: 42
Seguimiento de la pila:
[SqlException (0x80131904): Ya hay un objeto con el nombre 'vt_timezones_dstrules' en la base de datos.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +857338
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +734950
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +188
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1838
System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async) +192
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) +380
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +135
NHibernate.Tool.hbm2ddl.SchemaExport.Execute(Boolean script, Boolean export, Boolean format, Boolean throwOnError, TextWriter exportOutput, IDbCommand statement, String sql) +295
NHibernate.Tool.hbm2ddl.SchemaExport.Execute(Boolean script, Boolean export, Boolean justDrop, Boolean format, IDbConnection connection, TextWriter exportOutput) +210
NHibernate.Tool.hbm2ddl.SchemaExport.Execute(Boolean script, Boolean export, Boolean justDrop, Boolean format) +525
[HibernateException: Ya hay un objeto con el nombre 'vt_timezones_dstrules' en la base de datos.]
NHibernate.Tool.hbm2ddl.SchemaExport.Execute(Boolean script, Boolean export, Boolean justDrop, Boolean format) +594
NHibernate.Tool.hbm2ddl.SchemaExport.Create(Boolean script, Boolean export) +21
Castle.ActiveRecord.ActiveRecordStarter.CreateSchema() in c:\ccnet\CastleWorkDir\WorkingDirectory\ActiveRecord\Castle.ActiveRecord\Framework\ActiveRecordStarter.cs:191
[ActiveRecordException: Could not create the schema]
Castle.ActiveRecord.ActiveRecordStarter.CreateSchema() in c:\ccnet\CastleWorkDir\WorkingDirectory\ActiveRecord\Castle.ActiveRecord\Framework\ActiveRecordStarter.cs:195
VirtualTutor.GlobalApplication.Application_OnStart() in D:\Documents\Visual Studio 2005\Projects\VirtualTutor\VirtualTutor\GlobalApplication.cs:42
[Exception: An exception happened on Global application or on a module that run before MonoRail's module. MonoRail will not be initialized and further requests are going to fail. Fix the cause of the error reported below.]
Castle.MonoRail.Framework.EngineContextModule.Init(HttpApplication context) in c:\ccnet\CastleWorkDir\WorkingDirectory\MonoRail\Castle.MonoRail.Framework\EngineContextModule.cs:45
System.Web.HttpApplication.InitModules() +267
System.Web.HttpApplication.InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers) +1251
System.Web.HttpApplicationFactory.GetNormalApplicationInstance(HttpContext context) +243
System.Web.HttpApplicationFactory.GetApplicationInstance(HttpContext context) +106
System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +317
Yes, I know the exception is in Spanish (I think all error messages should be in English despite the IDE chossen language, but that's another question). The meaning of the exception is that it's trying to create the table
vt_timezones_dstrules two times. The second one obviously throws this exception :?
I've tried different things involving the 'Inverse' attribute with no success. I don't see anything wrong in the code. The DataBase we are using is SQL Server 2005 Developer Edition.
I've tried the same code but in a database with a schema named as the database (although the code creates the tables in the dbo schema). The results are that this time the table vt_timezones_dstrules is created two times: one in the dbo schema (this one is ok) but another in the database named schema, and the strange thing is that this last one has no ID field, only dstruleid and timezoneid fields. There is no primary key. If I remove the database named schema the exception on the first post still persists.
Please, can you confirm that it's not a bug in the NHibernate CreateSchema process?
Thank you in advance