views:

623

answers:

1

I have a legacy DB which uses a guid to map children to the parent entity.

In my domain layer, I'd prefer to obscure this quirk, so I'd like to have my parent entity look like this:

public class Parent
{
    virtual public int Id {get; protected set; }
    virtual public string ParentContent { get; set; }
    virtual public Guid ReferenceId { get; set; }
    virtual public IDictionary<int,Child> Children { get; set; }
}

public class Child
{
    virtual public int Id { get; protected set; }
    virtual public Parent { get; set; }
    virtual public string ChildContent { get; set; }
}

The parent would then map each Child.Id to Child in the Children dictionary. The Child mapping works fine, but I can't seem to find a reasonable mapping for the parent.

A field named ParentReferenceID exists in both Parent and Child tables, so I've attempted to map this with something like this:

        mapping.HasMany<Broker>(x => x.Children)
            .Table("Child")
            .KeyColumn("ParentReferenceID")
            .Inverse()
            .AsMap<long>(index=>index.Id,val=>val.Type<Broker>());

Unfortunately, this produces an error: The type or method has 2 generic parameter(s), but 1 generic argument(s) were provided. A generic argument must be provided for each generic parameter.

To simplify my problem, I started by trying Bag semantics, replacing the Parent's IDictionary with an IList. This was mapped using something like:

  mapping.HasMany<Broker>(x => x.Brokers)
     .Table("Child")
     .KeyColumn("ParentReferenceId")
     .Inverse()
     .AsBag();

That produces the more obvious exception, System.Data.SqlClient.SqlException: Operand type clash: uniqueidentifier is incompatible with int

Unfortunately, I can't seem to figure out the right way to tell it to join on the ReferenceID field. What's the right way to do that? I'd prefer the dictionary, but I'd be reasonably happy if I could even get the bag to work.

For clarity, I'm using a build of Fluent that is bundled with a recent SharpArchitecture pulled from git. The Fluent dll is marked version 1.0.0.594, but if a more recent build would help, I'm flexible.

A: 

Further digging has led me to a solution for the Bag case, though the dictionary is still giving me a bit of trouble.

The solution requires a patch to Fluent NHibernate's OneToManyPart mapping class. (Hat tip to This bug report: Could not map a one-to-many relationship where the key is not the primary key.

   mapping.HasMany(x => x.Children)
       .Table("Child").KeyColumn("ParentReferenceId")
       .PropertyRef("ReferenceId")
       .Inverse()
       .AsBag();

Theoretically, AsMap should work almost the same way, but for some reason that I'm not entirely clear on, it doesn't work for me. I'll explore that later, but I'm open to suggestions.

JasonTrue