如何在NHibernate中映射具有外键关系的两个表?

时间:2009-03-14 08:43:14

标签: c# .net database nhibernate nhibernate-mapping

有两个表,联系 Phone__number 。 Phone_number包含一列contact_id,它是联系表中id的外键。如何在Nhibernate中映射这两个表,以便在我的联系人类中获得PhoneNumbers列表。

1 个答案:

答案 0 :(得分:3)

域类:

public class Contact
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Phone> Phones { get; set; }
}

public class Phone
{
    public virtual int Id { get; set; }
    public virtual string Number { get; set; }
}

及其相应的映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    namespace="MyNamespace" assembly="MyAssembly"
    default-lazy="true">
  <class name="Phone" table="Phone__number">
    <id name="Id" column="pho_id" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="Number" column="pho_number" />
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    namespace="MyNamespace" assembly="MyAssembly"
    default-lazy="true">
  <class name="Contact" table="Contact">
    <id name="Id" column="cnt_id" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="Name" column="cnt_name" />
    <bag name="Phones">
      <key column="contact_id" />
      <one-to-many class="Phone" />
    </bag>
  </class>
</hibernate-mapping>

或者如果您更喜欢fluent表达映射的方式:

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate;

class Program
{
    static void Main(string[] args)
    {
        if (File.Exists("data.db3"))
        {
            File.Delete("data.db3");
        }

        using (var factory = CreateSessionFactory())
        {
            // Create schema and insert sample data
            using (var connection = factory.ConnectionProvider.GetConnection())
            {
                ExecuteQuery("create table contacts(cnt_id int, cnt_name string)", connection);
                ExecuteQuery("create table phones(pho_id int, pho_number string, contact_id int)", connection);
                ExecuteQuery("insert into contacts (cnt_id, cnt_name) values (1, 'Contact 1')", connection);
                ExecuteQuery("insert into phones (pho_id, pho_number, contact_id) values (1, '12345A', 1)", connection);
                ExecuteQuery("insert into phones (pho_id, pho_number, contact_id) values (2, '12345B', 1)", connection);
                ExecuteQuery("insert into phones (pho_id, pho_number, contact_id) values (3, '12345C', 1)", connection);
                ExecuteQuery("insert into phones (pho_id, pho_number, contact_id) values (4, '12345D', 1)", connection);
            }

            using (var session = factory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var contact = session.Get<Contact>(1);
                foreach (var phone in contact.Phones)
                {
                    Console.WriteLine(phone.Number);
                }
                tx.Commit();
            }
        }
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(
                SQLiteConfiguration.Standard.UsingFile("data.db3").ShowSql()
            )
            .Mappings(
                m => m.FluentMappings.AddFromAssemblyOf<Program>()
            )
            .BuildSessionFactory();
    }  

    static void ExecuteQuery(string sql, IDbConnection connection)
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = sql;
            command.ExecuteNonQuery();
        }
    }
}

public class Phone
{
    public virtual int Id { get; set; }
    public virtual string Number { get; set; }
}

public class Contact
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Phone> Phones { get; set; }
}

public class PhoneMap : ClassMap<Phone>
{
    public PhoneMap()
    {
        WithTable("phones");
        Id(x => x.Id, "pho_id");
        Map(x => x.Number, "pho_number");
    }
}

public class ContactMap : ClassMap<Contact>
{
    public ContactMap()
    {
        WithTable("contacts");
        Id(x => x.Id, "cnt_id");
        Map(x => x.Name, "cnt_name");
        HasMany<Phone>(x => x.Phones)
            .WithForeignKeyConstraintName("contact_id")
            .AsBag();
    }
}