Problem with N:M association (fluent mapping)

6 posts, 1 answers
  1. piotrekk
    piotrekk avatar
    6 posts
    Member since:
    Sep 2006

    Posted 19 Feb 2012 Link to this post

    Hello,

    I'm trying to define the model like this:
    public abstract class Element
    {
        public int Id { get; private set; }
        public string Name { get; set; }
        public IList<Catalog> Catalogs { get; private set; }
        public Element()
        {
            Catalogs = new List<Catalog>();
        }
    }
     
    public class Catalog: Element
    {
        public bool CanHoldCatalogs { get; set; }
         public IList<Element> Entries { get; private set; }
     
        public Catalog()
        {
            Entries = new List<Element>();
        }
    }
     
    //and of course, other classes inherited from Element

    I'm making the mapping like this:
    MappingConfiguration<Element> elementMap = new MappingConfiguration<Element>();
    elementMap.MapType().ToTable("Elements");
    elementMap.HasDiscriminator().ToColumn("class").HasColumnType("char").HasPrecision(10);
    elementMap.HasProperty(p => p.Id).IsIdentity(KeyGenerator.Autoinc);
     
    MappingConfiguration<Catalog> catalogMap = new MappingConfiguration<Catalog>();
    catalogMap.MapType().Inheritance(InheritanceStrategy.Vertical).ToTable("Catalogs");
    catalogMap.HasDiscriminatorValue("catalog");
     
    catalogMap.HasAssociation(a => a.Entries).WithOpposite(o => o.Catalogs)
        .MapJoinTable("CatalogEntries", (c,e) => new {CatalogID=c.Id,ElementId=c.Id});


    Model compiles without any errors, the database structure generated by OpenAccessContext looks good and I can do such operation:
    var root = new Catalog {Name = "root"};
    var home = new Catalog {Name = "home"};
    root.Entries.Add(home);
     
    context.Add(root);
    context.SaveChanges();

    Both 'root' and 'home' are correctly writed to the database, but nothing is saved to the join table, so there is no association created... :(

    best regards
    pk
  2. Answer
    Serge
    Admin
    Serge avatar
    375 posts

    Posted 22 Feb 2012 Link to this post

    Hello Piotr,

     Make sure that you have called IsManaged on both sides of the association, this will ensure that all records inserted in both collection are correctly persisted in the database. You code should look something like: 

    catalogMap.HasAssociation(a => a.Entries).WithOpposite(o => o.Catalogs)
        .IsManaged()
        .MapJoinTable("CatalogEntries", (c, e) => new { CatalogID = c.Id, ElementId = c.Id });
     
    elementMap.HasAssociation(o => o.Catalogs).WithOpposite(a => a.Entries)
        .IsManaged();

    I hope this helps. 

    All the best,
    Serge
    the Telerik team
    Telerik OpenAccess ORM Q1 2012 release is here! Check out what's new or download a free trial >>
  3. DevCraft banner
  4. piotrekk
    piotrekk avatar
    6 posts
    Member since:
    Sep 2006

    Posted 22 Feb 2012 Link to this post

    Hello Serge,

    You are absolutely right! Everything work OK now. Thank you for support.

    But testing my solution, I've found minor bug (?) in the fluent mapping N:M definition.
    Assume, we have:
    elementMap.HasAssociation(a => a.Catalogs).WithOpposite(o => o.Entries).IsManaged() //:)
    .MapJoinTable("CatalogEntries",
         (element, catalog) =>
    new { CatalogID = catalog.Id,ElementId = element.Id});
    (Note the revers order of fields declaration in join table).
    OpenAccess creates, as we can expect, the join table with two columns: 'CatalogID' and 'ElementID', but Element's IDs are put in column 'CatalogID' (and Catalog's IDs, of course, in 'ElementID'). Except that, everything work properly.

    best regards
    pk
  5. Serge
    Admin
    Serge avatar
    375 posts

    Posted 22 Feb 2012 Link to this post

    Hello Piotr,

     Are you sure that the catalog variable is in fact the one that represents the catalog object. Can you check its type and whether it is possible that they are switched. If that is not true, can you please send us the project to check this out in greater detail. 

    If what you are saying is correct we might have a serious bug on our hands.

    I am looking forward to resolving this issue with you. 

    Regards,
    Serge
    the Telerik team
    Telerik OpenAccess ORM Q1 2012 release is here! Check out what's new or download a free trial >>
  6. piotrekk
    piotrekk avatar
    6 posts
    Member since:
    Sep 2006

    Posted 22 Feb 2012 Link to this post

    Hmm, I've tested this twice - with the same effect.
    I'll send to you a small project as a support ticket.

    regards
    pk

    PS. I hope I'm wrong - no one likes huge errors...
  7. Serge
    Admin
    Serge avatar
    375 posts

    Posted 23 Feb 2012 Link to this post

    Hello Piotr,

     I will post my reply here, so that it is available to the community, if they ever faced the same problem. 

    Unfortunately this turned out to be a bug on our side, however it is not as grave as I initially thought. It is related to the fact the the identity is specified in the base class. We have added it to our internal issue tracker and you can expect a fix with the upcoming service pack. 

    For the time being though, you can fix the behaviour by simply switching the order in which you define the join table columns, always put the one referencing the mapping configuration type first. 

    Thank you for providing your solution it proved very helpful indeed.

    Kind regards,
    Serge
    the Telerik team
    Telerik OpenAccess ORM Q1 2012 release is here! Check out what's new or download a free trial >>
Back to Top
DevCraft banner