#nhibernate #configuration #castle-activerecord
#nhibernate #конфигурация #замок-activerecord
Вопрос:
Привет, это моя первая попытка с активной записью, я использую учебник с официального веб-сайта.
Сначала я создал некоторые правила:
[ActiveRecord("Users")]
public class User : ActiveRecordBase<User>
{
private IList<PhotoAlbum> _albums = new List<PhotoAlbum>();
[PrimaryKey]
public virtual int UserId { get; set; }
[BelongsTo("ProfilId")]
public virtual Profil Profil { get; set; }
[HasMany(typeof(PhotoAlbum),Table = "PhotoAlbums",
ColumnKey = "UserId",
Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList<PhotoAlbum> Album
{
get { return _albums; }
set { _albums = value; }
}
[Property]
public virtual string AzetId { get; set; }
[Property]
public virtual string Nick { get; set; }
[Property]
public virtual string SelfNick { get; set; }
}
[ActiveRecord("Profiles")]
public class Profil : ActiveRecordBase<Profil>
{
[PrimaryKey]
public int ProfilId { get; set; }
[Property]
public int Age { get; set; }
[Property]
public int Sex { get; set; }
[Property]
public string Region { get; set; }
[Property]
public string Town { get; set; }
[Property]
public bool WithPhoto { get; set; }
[Property]
public bool HasPhotoAlbum { get; set; }
}
[ActiveRecord("PhotoAlbums")]
public class PhotoAlbum : ActiveRecordBase<PhotoAlbum>
{
[PrimaryKey]
public int PhotoAlbumId { get; set; }
[Property]
public string Name { get; set; }
[Property]
public int NumberOfPhoto { get; set; }
}
Затем я создал файл конфигурации xml для активной записи:
<activerecord>
<config>
<add
key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver" />
<add
key="dialect"
value="NHibernate.Dialect.MsSql2008Dialect" />
<add
key="connection.provider"
value="NHibernate.Connection.DriverConnectionProvider" />
<add
key="connection.connection_string"
value="Data Source=testsqlexpress;Initial Catalog=TEST_AR_POKEC;Integrated Security=SSPI" />
</config>
</activerecord>
Наконец, я протестировал:
public static User GetUser(string nick, int sex,
string loc)
{
return new User
{
AzetId = new Random().Next()
.ToString(),
Nick = nick,
SelfNick = nick.ToUpper(),
Profil = new Profil()
{
Sex = sex,
Region = loc,
WithPhoto = true,
Age = new Random().Next(6, 99),
HasPhotoAlbum = true,
Town = loc
},
Album = new List<PhotoAlbum>
{
new PhotoAlbum
{
Name = "Me",
NumberOfPhoto =new Random().Next()
}
}
};
}
var source = new XmlConfigurationSource("ac.xml");
ActiveRecordStarter.Initialize(source,typeof(Profil),typeof(PhotoAlbum), typeof(User));
ActiveRecordStarter.CreateSchema();
var user = GetUser("tom",1,"DC");
user.Create();
Он завершился с этой ошибкой:
The ProxyFactoryFactory was not configured. Initialize
‘proxyfactory.factory_class’ property of the session-factory
configuration section with one of the available NHibernate.ByteCode
providers.
I google it and I think I found aswer I modified xml config for active record I added this part:
<add
key="proxyfactory.factory_class"
value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle"/>
I tested again. It created tabels in DB but this didn’t insert data to tables and I got this error:
object references an unsaved transient instance — save the transient
instance before flushing.
Here is StackTrace :
в NHibernate.Движок.Внешние ключи.GetEntityIdentifierIfNotUnsaved(строковое имя объекта, объект объекта, ISessionImplementor session) в NHibernate.Type.EntityType .Получите идентификатор (значение объекта, ISessionImplementor session) в NHibernate.Type.ManyToOneType .IsDirty(объект старый, объект текущий, логическое значение [] проверяется, ISessionImplementor session) в NHibernate.Type.TypeHelper .Найдите dirty(StandardProperty[] properties, Object[] currentState, Object[] previousState, Boolean[][] includeColumns, Boolean anyUninitializedProperties, ISessionImplementor session) в NHibernate.Сохраняется.Сущность.AbstractEntityPersister .Найдите dirty(объект[] currentState, объект[] previousState, объект entity, ISessionImplementor session) в NHibernate.Событие.По умолчанию.DefaultFlushEntityEventListener.DirtyCheck(событие FlushEntityEvent) в NHibernate.Событие.По умолчанию.DefaultFlushEntityEventListener.IsUpdateNecessary(событие FlushEntityEvent, логическое значение mightBeDirty) в NHibernate.Событие.По умолчанию.DefaultFlushEntityEventListener.OnFlushEntity(событие FlushEntityEvent) в NHibernate.Событие.По умолчанию.AbstractFlushingEventListener .FlushEntities(событие FlushEvent) в NHibernate.Событие.По умолчанию.AbstractFlushingEventListener .FlushEverythingToExecutions(событие FlushEvent) в NHibernate.Событие.По умолчанию.DefaultFlushEventListener.onFlush(событие FlushEvent) в NHibernate.Impl.SessionImpl.Сброс () в замке.ActiveRecord.Фреймворк.SessionFactoryHolder.ReleaseSession(сеанс ISession) в замке.ActiveRecord.ActiveRecordBase.InternalCreate(экземпляр объекта, логический сброс) в замке.ActiveRecord.ActiveRecordBase.Создайте (экземпляр объекта) в замке.ActiveRecord.ActiveRecordBase.Create() в SAMPLE_1 .Program.Main(строка [] аргументов) в E:C# PROJECTSSTUDYSTUDY.ORM Active RecordSAMPLE_1Program.cs: строка 51
в System.AppDomain._nExecuteAssembly(сборка RuntimeAssembly, строка [] аргументы) в системе.AppDomain.Выполните сборку (String assemblyFile, Evidence assemblySecurity, String[] args) в Microsoft.VisualStudio.Процесс хостинга.HostProc.RunUsersAssembly()
в системе.Многопоточность.ThreadHelper.ThreadStart_Context(состояние объекта)
в системе.Многопоточность.ExecutionContext.Run(ExecutionContext ExecutionContext, обратный вызов ContextCallback, состояние объекта, логическое игнорирование SyncCtx) в системе.Многопоточность.ExecutionContext.Run(ExecutionContext ExecutionContext, обратный вызов ContextCallback, состояние объекта) в системе.Многопоточность.ThreadHelper.ThreadStart()
Возможно, проблема здесь:
[BelongsTo("ProfilId")]
public virtual Profil Profil { get; set; }
и
[HasMany(typeof(PhotoAlbum),Table = "PhotoAlbums",
ColumnKey = "UserId",
Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList<PhotoAlbum> Album
{
get { return _albums; }
set { _albums = value; }
}
Я не уверен, но если я опустил эти два свойства (отношения), это работает хорошо, и данные вставляются в таблицу. Но с отношениями не работает.
ОТРЕДАКТИРОВАНО:
Если я указал каскадное поведение, оно работает…но почему?
[BelongsTo("ProfilId",
Cascade =CascadeEnum.All)]
public virtual Profil Profil { get; set; }
[HasMany(typeof(PhotoAlbum),
Table = "PhotoAlbums",
ColumnKey = "UserId",
Cascade = ManyRelationCascadeEnum.All)]
public IList<PhotoAlbum> Album
{
get { return _albums; }
set { _albums = value; }
}
Ответ №1:
Если вы не хотите Profile
, чтобы он автоматически сохранялся вместе с вашим User
объектом ( CascadeEnum.All
), вы должны сохранить этот объект отдельно в своем сеансе перед сохранением вашего User
.
Причина, по которой он выдает это исключение, когда каскадирование не включено, заключается в том, что ваш Profile
объект внутри вашего User
is transient
(не сохранен). Если вы включите каскадирование, он автоматически сохранит ваш объект и, следовательно, НЕ transient
будет.
Пример с каскадированием
ISession.Save(user);
Пример без каскадирования
ISession.Save(profile);
Isession.Save(user);