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>
我对在 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>