NHibernate映射一对多

NHibernate map one-to-many

我对在 NHIbernate 中做一对一映射有疑问。我有两个 class,专辑 class:

 public class Album
{
    private int id;
    private string name;
    private DateTime releaseDate;
    private int numberOfTracks;
    private int totalLength;
    private int mediaNumber;

    private Artist artist;
    private Label label;
    private Media media;

    private int reservationId = -1;
    private IList<Reservation> reservations = new List<Reservation>();
    private int sold;
    private int aviable;


    public int Id
    {
        get { return id; }
        set { id = value; }
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public DateTime ReleaseDate
    {
        get { return releaseDate; }
        set { releaseDate = value; }
    }

    public int NumberOfTracks
    {
        get { return numberOfTracks; }
        set { numberOfTracks = value; }
    }

    public int TotalLength
    {
        get { return totalLength; }
        set { totalLength = value; }
    }

    public int MediaNumber
    {
        get { return mediaNumber; }
        set { mediaNumber = value; }
    }

    public Artist Artist
    {
        get { return artist; }
        set { artist = value; }
    }

    public Label Label
    {
        get { return label; }
        set { label = value; }
    }

    public Media Media
    {
        get { return media; }
        set { media = value; }
    }

    public int Aviable
    {
        get { return aviable; }
        set { aviable = value; }

    }

    public int Sold
    {
        get { return sold; }
        set { sold = value; }
    }

    public string Lookup
    {
        get { return artist.Name + " - " + Name+ " ("+releaseDate.Year+")"; }
    }

    public int ReservationId
    {
        get { return reservationId; }
        set { reservationId = value; }
    }
    public IList<Reservation> Reservations
    {
        get { return reservations; }
        set { reservations = value; }
    }

    public int GenerateCode()
    {
        Random rnd = new Random();           
        return rnd.Next(1000, 10000);
    }

    public Album() 
    {

    }

    public Album(string inName, DateTime inReleaseDate, int inNumberOfTracks, int inTotalLength, int inMediaNumber, int inAviable, Artist inArtist, Label inLabel, Media inMedia)
    {
        Name = inName;
        ReleaseDate = inReleaseDate;
        NumberOfTracks = inNumberOfTracks;
        TotalLength = inTotalLength;
        MediaNumber = inMediaNumber;
        Artist = inArtist;
        Label = inLabel;
        Media = inMedia;
        Aviable = inAviable;
        Sold = 0;

    }

    public void AddReservation(string numberOfAlbums)
    {
        if (string.IsNullOrEmpty(numberOfAlbums) || !Regex.IsMatch(numberOfAlbums, @"^[0-9]"))
        {
            throw new InvalidReservationFormatException();
        }

        if (Convert.ToInt32(numberOfAlbums) > Aviable)
        {
            throw new InvalidReservationSizeException();
        }

        reservationId += 1;
        Reservation reservation = new Reservation(reservationId,GenerateCode(), Convert.ToInt32(numberOfAlbums));

        reservations.Add(reservation);
        Aviable -= Convert.ToInt32(numberOfAlbums);
    }

    public void PickUpReservation(string reservationCode)
    {
        if (Reservations.Count == 0)
        {
            throw new InvalidZeroReservationsException();
        }

        if (string.IsNullOrEmpty(reservationCode) || !Regex.IsMatch(reservationCode, @"^[0-9]") || Convert.ToInt32(reservationCode) > 9999 || Convert.ToInt32(reservationCode) < 1000)
        {
            throw new InvalidReservationCodeFormatException();
        }

        for (int i = 0; i < reservations.Count; i++)
        {
            if (reservations[i].ReservationCode == Convert.ToInt32(reservationCode))
            {
                Console.WriteLine(reservations[i].ReservationCode);
                Sold += reservations[i].NumberOfAlbums;
                reservations.RemoveAt(i);
                return;
            }
        }

        throw new InvalidReservationCodeException();
    }

    public void DropReservation(string reservationCode)
    {
        if (Reservations.Count == 0)
        {
            throw new InvalidZeroReservationsException();
        }

        if (string.IsNullOrEmpty(reservationCode) || !Regex.IsMatch(reservationCode, @"^[0-9]") || Convert.ToInt32(reservationCode) > 9999 || Convert.ToInt32(reservationCode) < 1000)
        {
            throw new InvalidReservationCodeFormatException();
        }

        for (int i = 0; i < reservations.Count; i++)
        {
            if (reservations[i].ReservationCode == Convert.ToInt32(reservationCode))
            {
                Aviable += reservations[i].NumberOfAlbums;
                reservations.RemoveAt(i);
                return;
            }
        }

        throw new InvalidReservationCodeException();
    }

    public void SellAlbum(string numberOfAlbums)
    {
        if (string.IsNullOrEmpty(numberOfAlbums) || !Regex.IsMatch(numberOfAlbums, @"^[0-9]"))
        {
            throw new InvalidReservationFormatException();
        }

        if (Convert.ToInt32(numberOfAlbums) > Aviable)
        {
            throw new InvalidReservationSizeException();
        }

        Aviable -= Convert.ToInt32(numberOfAlbums);
        Sold += Convert.ToInt32(numberOfAlbums);
    }

    public double GetIncome()
    {
        return this.Media.PricePerTrack(numberOfTracks)*Sold;
    }

    public bool HasArtist(int id)
    {
        return Artist.Id == id;
    }

    public bool HasLabel(int id)
    {
        return Label.Id == id;
    }

    public bool HasMedia(int id)
    {
        return Media.Id == id;
    }

}

和预订 class:

public class Reservation
{
    private int id;
    private int numberOfAlbums;
    private int reservationCode;
    private int reservationId;

    public int ReservationId
    {
        get { return reservationId; }
        set { reservationId = value; }
    }
    public int NumberOfAlbums
    {
        get { return numberOfAlbums; }
        set { numberOfAlbums = value; }
    }

    public int ReservationCode
    {
        get { return reservationCode; }
        set { reservationCode = value; }
    }

    public int Id
    {
        get { return id; }
        set { id = value; }
    }

    public Reservation ()
    {

    }
    public Reservation(int inId, int inReservationCode, int inNumberOfAlbums)
    {
        NumberOfAlbums = inNumberOfAlbums;
        ReservationCode = inReservationCode;
        Id = inId;
    }


}

所以我想映射那 2 个 classes。这是我的 XML:

    <?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="FromCDToVinyl.DomainModel" namespace="FromCDToVinyl.DomainModel">
  <class name="FromCDToVinyl.DomainModel.Album, FromCDToVinyl.DomainModel" table="Album" lazy="false" discriminator-value="Album">
    <id name="Id" column="Id">
      <generator class="native"/>
    </id>
    <property name="Name" column="Name"/>
    <property name="ReleaseDate" column="ReleaseDate"/>
    <property name="NumberOfTracks" column="NumberOfTracks"/>
    <property name="TotalLength" column="TotalLength"/>
    <property name="MediaNumber" column="MediaNumber"/>
    <property name="Aviable" column="Aviable"/>
    <property name="Sold" column="Sold"/>
    <property name="ReservationId" column="ReservationId"/>
    <many-to-one name="Artist" class="FromCDToVinyl.DomainModel.Artist, FromCDToVinyl.DomainModel" column="Artist"/>
    <many-to-one name="Label" class="FromCDToVinyl.DomainModel.Label, FromCDToVinyl.DomainModel" column="Label"/>
    <many-to-one name="Media" class="FromCDToVinyl.DomainModel.Media, FromCDToVinyl.DomainModel" column="Media"/>
    <list name="Reservations" table="Reservation" cascade="all-delete-orphan">
      <key column="Id"/>
      <index column="Position"/>
      <one-to-many class="FromCDToVinyl.DomainModel.Reservation, FromCDToVinyl.DomainModel"/>
    </list>
  </class>
</hibernate-mapping>

    <?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="FromCDToVinyl.DomainModel" namespace="FromCDToVinyl.DomainModel">
  <class name="FromCDToVinyl.DomainModel.Reservation, FromCDToVinyl.DomainModel" table="Reservation" lazy="false" discriminator-value="Reservation">
    <id name="ReservationId" column="ReservationId">
      <generator class="native"/>
    </id>
    <property name="Id" column="Id"/>
    <property name="ReservationCode" column="ReservationCode"/>
    <property name="NumberOfAlbums" column="NumberOfAlbums"/>
  </class>
</hibernate-mapping>

问题是每次我尝试向相册添加新预订时都会出现错误:

    An unhandled exception of type 'NHibernate.Exceptions.GenericADOException' occurred in NHibernate.dll

Additional information: could not insert: [FromCDToVinyl.DomainModel.Reservation][SQL: INSERT INTO Reservation (Id, ReservationCode, NumberOfAlbums) VALUES (?, ?, ?); select last_insert_rowid()]

有人可以帮忙吗?

是的,问题与 AK_ 建议的一致(谢谢)。我唯一改变的是

 `<id name="Id" column="Id"> <generator class="native"/>`

`<id name="Id" column="AlbumId"> <generator class="native"/>`

<list name="Reservations" table="Reservation" cascade="all-delete-orphan">
      <key column="Id"/>
      <index column="Position"/>
      <one-to-many class="FromCDToVinyl.DomainModel.Reservation, FromCDToVinyl.DomainModel"/>
</list>

<list name="Reservations" table="Reservation" cascade="all-delete-orphan">
      <key column="AlbumId"/>
      <index column="Position"/>
      <one-to-many class="FromCDToVinyl.DomainModel.Reservation, FromCDToVinyl.DomainModel"/>
</list>