Fluent NHibernate join single column from another

2020-06-03 02:05发布

问题:

I'm using Fluent NHibernate and have two tables;

Customer [ID, Name, LanguageID]

Languages [ID, Description]

I have a Customer entity with the following properties; ID, Name, LanguageID, Language

What I would like to do is to join to the Languages table to get the language description and put it in the language property of the customer entity.

I have tried using Join but I can't get it to use the LanguageID field on the customer table to join to the Languages table - it keeps wanting to use 'ID'.

My mapping looks like;

        Table("Customers");
        Not.LazyLoad();
        Id(c => c.ID).GeneratedBy.Assigned();
        Map(c => c.Name);
        Map(c => c.LanguageID);
        Join("Languages", join =>
        {
            join.KeyColumn("ID");
            join.Map(prop => prop.Language).Column("Description");
        });

回答1:

I haven't used Join before but I think you want the foreign key from Customer in your mapping:

    Table("ScriptActivities");
    Not.LazyLoad();
    Id(c => c.ID).GeneratedBy.Assigned();
    Map(c => c.Name);
    Map(c => c.LanguageID);
    Join("Languages", join =>
    {
        join.KeyColumn("LanguageID");
        join.Map(prop => prop.Language).Column("Description");
    });

Edited to add: The best example I could find on the join mapping is Ayende's blog. From that example, it appears to me that join is expecting the ID of the mapped object to be a foreign key in the joined table. Your schema has the joined table ID as a FK in the mapped object so join won't work. I suggest creating a view combining Customer and Language and mapping that.



回答2:

I think you can create an Entity for Language. Later in the Entity for Customer have a reference to that Entity.

public class Customer
{
    public virtual int Id { get; set; }
    public virtual string Name{ get; set; }
    public virtual Language Language { get; set; }
}

Then in the CutomerMap you should do:

public class CustomerMap : ClassMap<Customer>
{
    public CustomerMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        References(x => x.Language);
    }
}

Later when you call your costumers you can decide show the "instance.Language.Description"

For example in MVC, in the controller you can do:

 public ActionResult Index()
    {
        using (ISession session = NHibernateHelper.OpenSession())
        {
            var customers = session.Query<Customer>().Fetch(x => x.Language).ToList();
            return View(customers);
        }
    }

And in the View:

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.Name)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Language.Description)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
        @Html.ActionLink("Details", "Details", new { id=item.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id=item.Id })
    </td>
</tr>
}

Hope this helps.