流畅的NHibernate批量数据插入

本文关键字:数据 插入 NHibernate | 更新日期: 2023-09-27 18:15:10

我需要传输一些数据到其他数据库,但是当我启动这个mssql服务器冻结。Ds2行数约为25万。我做错了什么?

每次我尝试相同的函数首先看起来工作,然后在随机行上给出错误。也许是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中,但未在用户代码中处理

附加信息:could not insert: [Entity.Album.Album][SQL:INSERT INTO[相册]

(专辑名称,网站,年份,艺人)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表"。艺术家",列"ArtistId"。声明是终止。

流畅的NHibernate批量数据插入

有一些迹象,应该会导致答案。我们可以看到错误是:

附加信息:could not insert: [Entity.Album.][SQL: INSERT INTO[相册]
(专辑名称、网址、年份、艺人), ?, ?, ?);选择SCOPE_IDENTITY ()

当我们加载艺术家正确的方式…

Entity.Artist.Artist artist = Entity.Artist.Artist.READ
  .ById(Convert.ToInt32(ds2.Tables[0].Rows[i]["ArtistId"]));

问题可能在于不正确的集合映射。从Albumt到Artist的引用似乎是正确的:

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实例…并将它们的关系赋值给collection holder - Artist。这是一个很好的建议方法。好。

但是我们可以从NHibernate的逆()特性中获益,它将减少一些SQL语句…并使所有的插入更简单…所以像这样扩展你的艺术家映射:

// 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
}

查看更多详细信息