Мне нужно перенести некоторые данные в другие db, но когда я запустил это замораживание сервера mssql. Число строк ds2 составляет около 250 000. Что я делаю не так?
каждый раз, когда я пытаюсь использовать тот же funcion, сначала выглядит работающим, а после ошибки - случайной строкой. возможно, 5, 95 или 280. до тех пор, пока записи ошибок не будут действительны.
string inlineSql = "Select * from album";
DataSet ds2 = SqlHelper.ExecuteDataset(ConnectionString, CommandType.Text, inlineSql);
for (int i = 0; i < ds2.Tables[0].Rows.Count; i++)
{
Entity.Album.Album album = new Entity.Album.Album();
album.AlbumName = ds2.Tables[0].Rows[i]["AlbumName"].ToString();
album.WebSite = (Entity.Artist.WebSite)Convert.ToInt16(ds2.Tables[0].Rows[i]["WebSite"]);
album.Year = ds2.Tables[0].Rows[i]["Year"].ToString();
Entity.Artist.Artist artist = Entity.Artist.Artist.READ.ById(Convert.ToInt32(ds2.Tables[0].Rows[i]["ArtistId"]));
if (artist != null)
{
artist.AddAlbum(album);
album.Save();
}
}
Метод AddAlbum
public virtual void AddAlbum(Album.Album album)
{
album.Artist = this;
AlbumList.Add(album);
}
Метод сохранения
using (var session = NHibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(x);
transaction.Commit();
}
}
Ошибка в session.SaveOrUpdate(x);
Ошибка:
Исключение типа "NHibernate.Exceptions.GenericADOException" произошло в NHibernate.dll, но не было обработано в коде пользователя
Дополнительная информация: не удалось вставить: [Entity.Album.Album] [SQL: INSERT INTO [Album]
(AlbumName, WebSite, Year, ArtistId) VALUES (?,?,?,?); выберите SCOPE_IDENTITY()]
AlbumMap
public class AlbumMap : ClassMap<Album> { public AlbumMap() { Id(x => x.AlbumId); Map(x => x.AlbumName); Map(x => x.WebSite).CustomType<short>(); Map(x => x.Year); HasMany(x => x.LyricList).Table("Lyric").KeyColumn("AlbumId").Cascade.All().Not.LazyLoad(); References(x => x.Artist).Column("ArtistId").ForeignKey("ArtistId").Fetch.Join(); } }
ArtistMap
public class ArtistMap : ClassMap<Artist>
{
public ArtistMap()
{
Id(x => x.ArtistId);
Map(x => x.ArtistName);
Map(x => x.ArtistURL);
Map(x => x.ImgName);
Map(x => x.ImgURL);
Map(x => x.Alfabet);
Map(x => x.SeoLink);
Map(x => x.WebSite).CustomType<short>();
HasMany(x => x.AlbumList).Table("Album").KeyColumn("ArtistId").Cascade.All().Not.LazyLoad();
}
}
Больше исключений
Оператор INSERT противоречил ограничениям FOREIGN KEY "FKA0CE20AA48AC4CAD". Конфликт произошел в базе данных "LYRICSWEB", таблице "dbo.Artist", в столбце "ArtistId". Заявление было прекращено.
Есть некоторые указания, которые должны привести к ответу. Мы видим, что ошибка:
Дополнительная информация: не удалось вставить: [Entity.Album.Album] [SQL: INSERT INTO [Album]
(AlbumName, WebSite, Year, ArtistId) VALUES (?,?,?,?); выберите SCOPE_IDENTITY()]
в то время как мы грузим художник правильным способом...
Entity.Artist.Artist artist = Entity.Artist.Artist.READ
.ById(Convert.ToInt32(ds2.Tables[0].Rows[i]["ArtistId"]));
Проблема заключается в неправильном сопоставлении коллекции. Ссылка от альбома к художнику кажется правильной:
public AlbumMap()
{
..
References(x => x.Artist)
.Column("ArtistId")
.ForeignKey("ArtistId")
.Fetch.Join();
}
Но другой конец этого отношения отображается следующим образом:
// wrong
public ArtistMap()
{
..
HasMany(x => x.AlbumList)
.Table("Album")
.KeyColumn("AlbumId") // wrong
.Cascade.All().Not.LazyLoad();
}
Оба эти отношения одинаковы ! Они отображаются только с разных концов (с точки зрения коллекции и от предполагаемого владельца коллекции).
Это означает, что столбец отображения должен быть одним и тем же, то есть не "AlbumId"
а "ArtistId"
// correct
public ArtistMap()
{
..
HasMany(x => x.AlbumList)
.Table("Album")
.KeyColumn("ArtistId") // this is the relation
.Cascade.All().Not.LazyLoad();
}
Поскольку NHibernate загружает некоторого исполнителя и его коллекцию AlubmList.., это может привести к некоторым неожиданным заявлениям вставки... исправление этого сопоставления должно помочь...
Inverse()
Мы работаем с экземплярами Album
... и мы назначаем их отношение к обладателю коллекции - Artist
. Это хорошо и предлагается, как это сделать. Хорошо.
Но мы можем извлечь выгоду из функции NHibernate под названием Inverse(), которая уменьшит количество операторов SQL... и сделает все вложение более простым... поэтому расширьте сопоставление с Artist следующим образом:
// correct
public ArtistMap()
{
..
HasMany(x => x.AlbumList)
.Table("Album")
.KeyColumn("ArtistId") // this is the relation
.Cascade.All()
.Not.LazyLoad()
.Inverse(); // ESSENTIAL improvement of generated SQL
}
Проверьте это для более подробной информации.
albumId
не включил идентичность ...