Question

Hi this is my first attempt with Active Record I use tutorial from official web site.

First I created some etities:

[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; }
}

Then I created xml config file for active record:

<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=test\sqlexpress;Initial Catalog=TEST_AR_POKEC;Integrated Security=SSPI" />
  </config>

</activerecord>

Finnaly I tested:

    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();

It finished with this error:

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 :

at NHibernate.Engine.ForeignKeys.GetEntityIdentifierIfNotUnsaved(String entityName, Object entity, ISessionImplementor session) at NHibernate.Type.EntityType.GetIdentifier(Object value, ISessionImplementor session) at NHibernate.Type.ManyToOneType.IsDirty(Object old, Object current, Boolean[] checkable, ISessionImplementor session) at NHibernate.Type.TypeHelper.FindDirty(StandardProperty[] properties, Object[] currentState, Object[] previousState, Boolean[][] includeColumns, Boolean anyUninitializedProperties, ISessionImplementor session) at NHibernate.Persister.Entity.AbstractEntityPersister.FindDirty(Object[] currentState, Object[] previousState, Object entity, ISessionImplementor session) at NHibernate.Event.Default.DefaultFlushEntityEventListener.DirtyCheck(FlushEntityEvent event) at NHibernate.Event.Default.DefaultFlushEntityEventListener.IsUpdateNecessary(FlushEntityEvent event, Boolean mightBeDirty) at NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent event) at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent event) at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) at NHibernate.Impl.SessionImpl.Flush() at Castle.ActiveRecord.Framework.SessionFactoryHolder.ReleaseSession(ISession session) at Castle.ActiveRecord.ActiveRecordBase.InternalCreate(Object instance, Boolean flush) at Castle.ActiveRecord.ActiveRecordBase.Create(Object instance) at Castle.ActiveRecord.ActiveRecordBase.Create() at SAMPLE_1.Program.Main(String[] args) in E:\C# PROJECTS\STUDY\STUDY.ORM\Active Record\SAMPLE_1\Program.cs:line 51
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

Maybe problem is here:

[BelongsTo("ProfilId")]
public virtual Profil Profil { get; set; }

and

[HasMany(typeof(PhotoAlbum),Table = "PhotoAlbums",
    ColumnKey = "UserId", 
    Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList<PhotoAlbum> Album
{
    get { return _albums; }
    set { _albums = value; }
}

I am not sure but if I omitted these two properties (relationship) it works good and data are inserted into table. But with relationship doesn’t work.

EDITED:

If I specified Cascade behavior it works...but why?

   [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; }
    }
Était-ce utile?

La solution

If you are not wanting the Profile to be saved with your User object automatically (CascadeEnum.All) you must save this object separately in your session before saving your User.

The reason it's throwing that exception when cascading is not turned on is because your Profile object within your User is transient (not saved). If you turn on cascading it automatically saves your object and is therefore NOT transient.

Example with cascading

ISession.Save(user);

Example without cascading

ISession.Save(profile);
Isession.Save(user);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top