Import, an unsaved transient instance error thrown..

Topics: Customizing Orchard, Writing modules
Apr 15, 2014 at 11:29 PM
Recipe execution with id 28052a693f4742db8d84507543ae9d1d was cancelled because the "Data" step failed to execute. The following exception was thrown: object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave. Type: Orchard.Taxonomies.Models.TermPartRecord, Entity: Orchard.Taxonomies.Models.TermPartRecord. Refer to the error logs for more information.

This is occurring when I add taxonomy terms to my part on import.

You will note that I could use the taxonomy part in my recipe instead of generating them on the fly, due to the expensive data queries to generate the import recipe in the first place, the terms are already in the xml to begin with. So Instead of requesting the database to do the queries twice, once to generate xml, and the second to generate a string, I thought it easier and faster to do it as ingestion occurs.

on this line
var workPerson = this.taxonomyService.GetTaxonomyByName(Taxonomies.WorkPersons);
code:

protected override void Importing(AlbumPart part, Orchard.ContentManagement.Handlers.ImportContentContext context)
{
  ------  Handle Part Properties 

    -- Add terms 
    var recordingPerson = this.taxonomyService.GetTaxonomyByName(Taxonomies.RecordingPersons);
    var persons = context.Data.Element(Parts.AlbumPart)
                              .Element("Tracks")
                              .XPathSelectElements("//Tracks/Track/Recording/Person[@taxonomy_RecordingPerson]");
    List<TermPart> terms = this.taxonomyService.GetTermsForContentItem(part.ContentItem.Id, Taxonomies.RecordingPersons).ToList();

    foreach (var person in persons)
    {
        // Add term to the Taxonomies
        var termName = person.Attribute("taxonomy_RecordingPerson").Value;
        var term = this.taxonomyService.NewTerm(recordingPerson);
        term.Container = recordingPerson.ContentItem;
        term.Name = termName;
        term.Slug = string.Concat(recordingPerson.Slug, "/", term.Name).ToLower().Replace(" ", "-");
        if (this.taxonomyService.GetTerms(recordingPerson.Id).Any(t => t.Name == termName) == false)
        {
            this.contentManager.Create(term, VersionOptions.Published);
        }
        if (terms.Any(t => t.Name == termName) == false)
        {
            terms.Add(term);
        }
    }
    this.taxonomyService.UpdateTerms(part.ContentItem, terms, Taxonomies.RecordingPersons);

    var workPerson = this.taxonomyService.GetTaxonomyByName(Taxonomies.WorkPersons);
    persons = context.Data.Element(Parts.AlbumPart)
                          .Element("Tracks")
                          .XPathSelectElements("//Tracks/Track/Recording/Work/Person[@taxonomy_WorkPerson]");
    terms = this.taxonomyService.GetTermsForContentItem(part.ContentItem.Id, Taxonomies.WorkPersons).ToList();

    foreach (var person in persons)
    {
        // Add term to the Taxonomies
        var termName = person.Attribute("taxonomy_WorkPerson").Value;
        var term = this.taxonomyService.NewTerm(workPerson);
        term.Container = workPerson.ContentItem;
        term.Name = termName;
        term.Slug = string.Concat(workPerson.Slug, "/", term.Name).ToLower().Replace(" ", "-");
        if (this.taxonomyService.GetTerms(workPerson.Id).Any(t => t.Name == termName) == false)
        {
            this.contentManager.Create(term, VersionOptions.Published);
        }
        if (terms.Any(t => t.Name == termName) == false)
        {
            terms.Add(term);
        }
    }
    this.taxonomyService.UpdateTerms(part.ContentItem, terms, Taxonomies.WorkPersons);
}
The terms are retreived from an xml that is stored as a string in the info set.

I tried to request a new transactions from the transaction manager but that did not work.
Apr 15, 2014 at 11:54 PM
Edited Apr 15, 2014 at 11:55 PM
Solved:

Here is the better code, (note better) not saying this is good.

My code was creating duplicate terms from the taxonomy service. Once that was resolved, no more errors.

var recordingPerson = this.taxonomyService.GetTaxonomyByName(Taxonomies.RecordingPersons);
var persons = context.Data.Element(Parts.AlbumPart)
                          .Element("Tracks")
                          .XPathSelectElements("//Tracks/Track/Recording/Person[@taxonomy_RecordingPerson]");
List<TermPart> terms = this.taxonomyService.GetTermsForContentItem(part.ContentItem.Id, Taxonomies.RecordingPersons).ToList();

foreach (var person in persons)
{
    // Add term to the Taxonomies
    var termName = person.Attribute("taxonomy_RecordingPerson").Value;
    var term = this.taxonomyService.GetTermByName(recordingPerson.Id, termName);
    if (term == null)
    {
        term = this.taxonomyService.NewTerm(recordingPerson);
        term.Container = recordingPerson.ContentItem;
        term.Name = termName;
        term.Slug = string.Concat(recordingPerson.Slug, "/", term.Name).ToLower().Replace(" ", "-");
        this.contentManager.Create(term, VersionOptions.Published);
    }
    if (terms.Any(t => t.Name == termName) == false)
    {
        terms.Add(term);
    }
}
this.taxonomyService.UpdateTerms(part.ContentItem, terms, Taxonomies.RecordingPersons);

var workPerson = this.taxonomyService.GetTaxonomyByName(Taxonomies.WorkPersons);
persons = context.Data.Element(Parts.AlbumPart)
                      .Element("Tracks")
                      .XPathSelectElements("//Tracks/Track/Recording/Work/Person[@taxonomy_WorkPerson]");
terms = this.taxonomyService.GetTermsForContentItem(part.ContentItem.Id, Taxonomies.WorkPersons).ToList();

foreach (var person in persons)
{
    // Add term to the Taxonomies
    var termName = person.Attribute("taxonomy_WorkPerson").Value;
    var term = this.taxonomyService.GetTermByName(workPerson.Id, termName);
    if (term == null)
    {
        term = this.taxonomyService.NewTerm(workPerson);
        term.Container = workPerson.ContentItem;
        term.Name = termName;
        term.Slug = string.Concat(workPerson.Slug, "/", term.Name).ToLower().Replace(" ", "-");
        this.contentManager.Create(term, VersionOptions.Published);
    }

    if (terms.Any(t => t.Name == termName) == false)
    {
        terms.Add(term);
    }
}
this.taxonomyService.UpdateTerms(part.ContentItem, terms, Taxonomies.WorkPersons);