Search code examples
c#nhibernatenhibernate-mappingunit-of-worknhibernate-mapping-by-code

Loquacious many-to-many not updating database when child added


Consider the following models/mappings

[DataContract]
public class CustomPhrase : ModelBase
{
  private ICollection<EnglishPhrase> translations;

  public CustomPhrase()
  {
    this.translations = new List<EnglishPhrase>();
  }

  [DataMember]
  public virtual string Phrase { get; set; }

  [DataMember]
  public virtual IEnumerable<EnglishPhrase> Translations
  { 
    get
    {
      return this.translations;
    }
  }
}

[DataContract]
public class EnglishPhrase : ModelBase
{
  private ICollection<CustomPhrase> translations;

  public CustomPhrase()
  {
    this.translations = new List<CustomPhrase>();
  }

  [DataMember]
  public virtual string Phrase { get; set; }

  [DataMember]
  public virtual IEnumerable<CustomPhrase> Translations
  { 
    get
    {
      return this.translations;
    }
  }
}

public CustomPhraseMap() : base("Translation_CustomPhrase", "CustomPhraseId")
{
  this.Property(x => x.Phrase);
  this.Set(
    x => x.Translations,
    map =>
      {
        map.Table("Translation_Link");
        map.Key(key => key.Column("CustomPhraseId"));
        map.Access(Accessor.Field);
        map.Cascade(Cascade.All);
      },
    map => map.ManyToMany(c => c.Column("EnglishPhraseId"))
    );
}

public EnglishPhraseMap() : base("Translation_EnglishPhrase", "EnglishPhraseId")
{
  this.Property(x => x.Phrase);
  this.Set(
    x => x.Translations,
    map =>
      {
        map.Table("Translation_Link");
        map.Key(key => key.Column("EnglishPhraseId"));
        map.Access(Accessor.Field);
        map.Cascade(Cascade.All);
      },
    map => map.ManyToMany(c => c.Column("CustomPhraseId"))
    );
}

If I execute this bit of code, the entities are added to the database but the link table Translation_Link is not updated.

var customPhrase = new CustomPhrase { Phrase = "Gobble" };
var englishPhrase = new EnglishPhrase { Phrase = "Hello" };
customPhrase.AddTranslation(englishPhrase);
this.customPhraseRepository.Add(customPhrase);

I'm not sure if this is a mapping problem, or a repository configuration problem. Maybe I'm adding the child at the wrong time??

Has anyone else come across this problem before and been able to fix it?


Solution

  • I managed to fix this problem using a transaction.

      try
      {
        unitOfWork.BeginTransaction();
    
        var custom = this.customPhraseRepository.FindCustomPhraseByPhrase(customPhrase);
        if (custom == null)
        {
          custom = new CustomPhrase() { Phrase = customPhrase };
          this.customPhraseRepository.Add(custom);
        }
    
        var english = this.englishPhraseRepository.FindEnglishPhraseByPhrase(englishPhrase);
        if (english == null)
        {
          english = new EnglishPhrase() { Phrase = englishPhrase };
          this.englishPhraseRepository.Add(english);
        }
    
        custom.AddTranslation(english);
        this.customPhraseRepository.Update(custom);
    
        unitOfWork.EndTransaction();
      }
      catch (Exception)
      {
        unitOfWork.RollBack();
      }
      finally
      {
        unitOfWork.Dispose();
      }