У нас возникает проблема с NHibernate, которая периодически вызывает запрос с неправильным столбцом SQL. Если перезапустить приложение, проблема перестает появляться (иногда требуется более одного перезапуска). Когда возникает проблема, в течение всего жизненного цикла этого процесса он всегда создает неправильный SQL для затронутого объекта. Это не всегда один и тот же объект.Создание неправильных столбцов по запросам
Это приложение ASP.NET, в котором SessionFactory создается во время события Application_Start. Вся конфигурация и сопоставление выполняются с помощью кода.
У нас больше нет идей, как тестировать или отлаживать приложение, и я предполагаю, что в NHibernate есть некоторая ошибка, так как приложение исправляет себя при перезагрузке. Любые идеи/советы будут высоко оценены!
Here's пример:
Entity
namespace Example.Clinicas
{
public partial class Clinica : Entidade // Abstract base class that has a property Handle
{
public virtual string Ddd { get; set; }
public virtual string Ddd2 { get; set; }
public virtual long? Duracao { get; set; }
public virtual string Numero { get; set; }
public virtual string Numero2 { get; set; }
public virtual string Prefixo { get; set; }
public virtual string Prefixo2 { get; set; }
public virtual long? HandlePrestador { get; set; }
public virtual Example.Prestadores.Prestador Prestador { get; set; }
}
}
Mapping
namespace Example.Clinicas.Mappings
{
public class ClinicaMapping : ClassMapping<Clinica>
{
public ClinicaMapping()
{
Table("CLI_CLINICA");
Id(x => x.Handle, map =>
{
map.Column("HANDLE");
map.Generator(Generators.Sequence, g => g.Params(new { sequence = "SEQ_AUTO1816" }));
});
Property(x => x.Ddd, map => map.Column(c=>
{
c.Name("DDD1");
c.Length(4);
}));
Property(x => x.Ddd2, map => map.Column(c=>
{
c.Name("DDD2");
c.Length(4);
}));
Property(x => x.Duracao, map => map.Column("INTERVALOAGENDA"));
Property(x => x.Numero, map => map.Column(c=>
{
c.Name("NUMERO1");
c.Length(5);
}));
Property(x => x.Numero2, map => map.Column(c=>
{
c.Name("NUMERO2");
c.Length(5);
}));
Property(x => x.Prefixo, map => map.Column(c=>
{
c.Name("PREFIXO1");
c.Length(5);
}));
Property(x => x.Prefixo2, map => map.Column(c=>
{
c.Name("PREFIXO2");
c.Length(5);
}));
Property(x => x.HandlePrestador, map => map.Column("PRESTADOR"));
ManyToOne(x => x.Prestador, map =>
{
map.Column("PRESTADOR");
map.Insert(false);
map.Update(false);
});
}
}
}
Команда
Session.Query<Clinica>().FirstOrDefault();
Сгенерированный SQL
select HANDLE489_,
DDD2_489_,
DDD3_489_,
INTERVAL4_489_,
NUMERO5_489_,
NUMERO6_489_,
PREFIXO7_489_,
FATURADE8_489_,
PRESTADOR489_
from (select clinica0_.HANDLE as HANDLE489_,
clinica0_.DDD1 as DDD2_489_,
clinica0_.DDD2 as DDD3_489_,
clinica0_.INTERVALOAGENDA as INTERVAL4_489_,
clinica0_.NUMERO1 as NUMERO5_489_,
clinica0_.NUMERO2 as NUMERO6_489_,
clinica0_.PREFIXO1 as PREFIXO7_489_,
clinica0_.FATURADEPARCELAMENTO as FATURADE8_489_,
clinica0_.PRESTADOR as PRESTADOR489_
from CLI_CLINICA clinica0_)
where rownum <= 1
Исключение
ORA-00904: "CLINICA0_"."FATURADEPARCELAMENTO": invalid identifier
Интересные наблюдения:
- Это, скорее всего, влияет на большую entit (который имеет большее количество свойств), но также иногда затрагивает небольшие субъекты;
- Сгенерированный SQL всегда имеет такое же количество столбцов, что и отображаемые свойства;
- Столбцы на SQL находятся в том же порядке, что и сопоставленные свойства в классе сопоставления;
- Неправильный столбец заменит существующий;
- Неправильный столбец является допустимым столбцом в другой сопоставленной сущности;
- Между затронутым объектом и тем, у которого есть неправильный столбец, нет никакой связи;
Другие детали:
- версии .NET: 4,0
- NHibernate Версия: 3.3.3.400
- Mapping по коду: NHibernate.Mapping.ByCode
- Конфигурация с помощью кода: NHibernate.Cfg
нагрузки Отображения
var mapper = new ModelMapper();
foreach (var assembly in resolver.GetAssemblies()) // resolver is a class that gets all the assemblies for the current application
mapper.AddMappings(assembly.GetExportedTypes());
var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
return mapping;
SessionFactory конфигурации
var configure = new Configuration();
configure.DataBaseIntegration(x =>
{
x.Dialect<Oracle10gDialect>(); // Custom class
x.ConnectionString = ConnectionString;
x.BatchSize = 100;
x.Driver<OracleMultiQueryDataClientDriver>(); // Custom class
x.MaximumDepthOfOuterJoinFetching = 10;
x.Timeout = 250;
x.PrepareCommands = true;
x.HqlToSqlSubstitutions = "true 'S', false 'N', yes 'S', no 'N'";
x.LogFormattedSql = true;
x.LogSqlInConsole = true;
x.AutoCommentSql = true;
x.IsolationLevel = IsolationLevel.ReadCommitted;
x.ConnectionProvider<ConnectionProvider>(); // Custom class
});
configure.Properties.Add(new KeyValuePair<string, string>("hibernate.command_timeout", "250"));
configure.Proxy(x => x.ProxyFactoryFactory<NHibernate.Bytecode.DefaultProxyFactoryFactory>());
configure.LinqToHqlGeneratorsRegistry<LinqToHqlGeneratorsRegistry>();
configure.CurrentSessionContext<NHibernate.Context.WebSessionContext>();
var mapping = GetMappings(); // Method showed above
mapping.autoimport = false;
configure.AddMapping(mapping);
var listener = new AuditEventListener();
configure.EventListeners.PostInsertEventListeners = new IPostInsertEventListener[] { listener };
configure.EventListeners.PostUpdateEventListeners = new IPostUpdateEventListener[] { listener };
configure.SessionFactory().GenerateStatistics();
return configure;
У вас есть несколько объектов, сопоставленных с одной и той же базой данных? – rivarolle
Есть некоторые, но не в этом случае. Клиника является единственным сопоставленным объектом в таблице CLI_CLINICA. –
Всегда ли ссылается на тот же недопустимый столбец? – mxmissile