Berryl
Berryl

Reputation: 12833

not understanding this error

Given the code and mapping below, Why am I getting this error?

Error from Failing test

    [Test]
    public void Cascade_Can_Persist_Hero_Without_Epic()
    {
        _epic = new Epic("illiad");
        var hero = new GreekHero("ted");
        hero.SetEpic(_epic);
        _session.SaveOrUpdate(_epic);
        _session.Flush();
        _session.Evict(_epic);
        Assert.That(_epic.IsPersistent());
        Assert.That(hero.IsPersistent());

        var found = _session.Get<GreekHero>(hero.Id);
        found.Look();

        Assert.That(found, Is.EqualTo(hero));
    }

NHibernate: select next_hi from hibernate_unique_key
NHibernate: update hibernate_unique_key set next_hi = @p0 where next_hi = @p1;@p0 = 6 [Type: Int32 (0)], @p1 = 5 [Type: Int32 (0)]
NHibernate: select next_hi from hibernate_unique_key
NHibernate: update hibernate_unique_key set next_hi = @p0 where next_hi = @p1;@p0 = 7 [Type: Int32 (0)], @p1 = 6 [Type: Int32 (0)]
NHibernate: 
    INSERT INTO Epic (EpicName, EpicId) 
    VALUES (@p0, @p1);
        @p0 = 'illiad' [Type: String (0)], 
        @p1 = 163840 [Type: Int32 (0)]
NHibernate: 
    INSERT INTO GreekHero (HeroName, EpicId, GreekHeroId) 
    VALUES (@p0, @p1, @p2);
        @p0 = 'ted' [Type: String (0)], 
        @p1 = 163840 [Type: Int32 (0)], 
        @p2 = 196608 [Type: Int32 (0)]
Test 'Core.Data.Tests.NHibernate.Bootstraps.MappingTests.CollectionMappingConstraintTests.Cascade_Can_Persist_Hero_Without_Epic' failed:
    NHibernate.Exceptions.GenericADOException : could not insert: 
    [Core.TestingSupport.GreekGods.Domain.GreekHero#196608][SQL: INSERT INTO GreekHero (HeroName, EpicId, GreekHeroId) VALUES (?, ?, ?)]
  ----> System.Data.SqlServerCe.SqlCeException : 
  A foreign key value cannot be inserted because a corresponding primary key value does not exist. [ Foreign key constraint name = FK253126F517FE25F6 ]

Object Model (parent)

public class Epic : Entity
{
    ...

    [UsedImplicitly] // NHib uses this
    public Epic() {
        _greekHeroes = new HashedSet<GreekHero>();
    }

    /// <summary>
    /// The backing store for order items. NHib will set this when loaded from the db.
    /// </summary>
    private readonly Iesi.Collections.Generic.ISet<GreekHero> _greekHeroes;

    /// <summary>
    /// An enumeration of greek heros for public consumption.
    /// </summary>
    public virtual IEnumerable<GreekHero> GreekHeroes { get { return _greekHeroes; } }

    public virtual bool AddItem(GreekHero newItem)
    {
        if (!ReferenceEquals(newItem, null) && _greekHeroes.Add(newItem))
        {
            newItem.SetEpic(this);
            return true;
        }
        return false;
    }

    public virtual bool RemoveItem(GreekHero itemToRemove)
    {
        if (!ReferenceEquals(itemToRemove, null) && _greekHeroes.Remove(itemToRemove))
        {
            itemToRemove.SetEpic(null);
            return true;
        }
        return false;
    }
}

Object Model (child)

public class GreekHero : Entity
{
    ...

    #endregion

    #region Epic (a Greek Hero may be associated with an Epic)

    /// <summary>
    /// The Epic associated with this Greek Hero.
    /// </summary>
    public virtual Epic Epic { get; protected set; }

    /// <summary>
    /// This enforces referential integrity in the object model between this <see cref="GreekHero"/>
    /// and the <see cref="Domain.Epic.GreekHeroes"/>.
    /// </summary>
    /// <param name="epic">The new epic associated with this hero.</param>
    /// <remarks><seealso cref="Domain.Epic.AddItem"/> and <seealso cref="Domain.Epic.RemoveItem"/></remarks>
    public virtual void SetEpic(Epic epic)
    {
        var prevEpic = Epic;
        if (epic == prevEpic) return;

        Epic = epic;

        if (!ReferenceEquals(prevEpic, null))
            prevEpic.RemoveItem(this);

        if (!ReferenceEquals(epic, null))
            epic.AddItem(this);
    }

    #endregion
}

HBM Mapping (Parent)

<id name="Id">
  <column name="EpicId" />
  <generator class="hilo" />
</id>

<natural-id>
  <property name="EpicName" length="30" />
</natural-id>

<set name="GreekHeroes"
     cascade="all-delete-orphan"
     inverse="true"
     access="field.camelcase-underscore">
  <key column="GreekHeroId" />
  <one-to-many class="GreekHero"/>
</set>

HBM Mapping (child)

<id name="Id">
  <column name="GreekHeroId" />
  <generator class="hilo" />
</id>

<natural-id>
  <property name="HeroName" length="30" />
</natural-id>

<many-to-one name="Epic" column="EpicId" />

Upvotes: 0

Views: 171

Answers (1)

Oskar Berggren
Oskar Berggren

Reputation: 5629

The <key> element in <set> indicates the column in the child table where the key of the parent is to be stored. In your case it should be "EpicId" since that is what you state in the <many-to-one>.

Upvotes: 1

Related Questions