如何在NHibernate中使用InsertBuilder实现批量插入时生成唯一Guid
解决NHibernate InsertBuilder批量插入生成唯一Guid的问题
问题原因
你当前的写法报错是因为InsertBuilder会将操作转换为SQL语句在数据库端执行,而guidGen.Generate(s.GetSessionImplementation(), c)是客户端方法调用,无法被NHibernate解析为合法的SQL表达式,因此抛出“The property expression must refer to a property of c(Attachment)”错误。
下面提供两种可行的解决方案:
方案一:利用数据库内置Guid生成函数(推荐)
直接让数据库生成唯一Guid,性能更优且无需加载数据到内存,适合大数据量批量插入场景。根据你使用的数据库调整函数名:
示例代码(SQL Server)
var mailIds = batch.Select(x => x.Id); Dao.Evaluate(s => s.Query<Mail>() .Where(es => mailIds.Contains(es.Id)) .InsertBuilder() .Into<Attachment>() // 使用SQL Server的NEWID()函数生成唯一Guid .Value(c => c.Id, Projections.SqlFunction("newid", NHibernateUtil.Guid)) .Value(c => c.Filename, fileName) .Value(c => c.Type.Id, attachmentType.Id) .Value(c => c.Media.Id, media.Id) .Value(c => c.LastChangedBy, IdentityHelper.CurrentUserName) .Value(c => c.LastChangedOn, DateTime.Now) .Value(c => c.CreatedBy, IdentityHelper.CurrentUserName) .Value(c => c.CreatedOn, DateTime.Now) .Insert());
其他数据库适配
- PostgreSQL:替换为
Projections.SqlFunction("uuid_generate_v4", NHibernateUtil.Guid)(需先安装uuid-ossp扩展) - MySQL:替换为
Projections.SqlFunction("uuid", NHibernateUtil.Guid)
方案二:客户端预生成Guid后批量插入
如果需要在客户端控制Guid生成逻辑,可先将源数据加载到内存,生成包含唯一Guid的Attachment集合,再执行批量插入:
示例代码
var mailIds = batch.Select(x => x.Id); // 1. 加载需要关联的Mail数据到内存 var targetMails = Dao.Evaluate(s => s.Query<Mail>().Where(es => mailIds.Contains(es.Id)).ToList()); // 2. 生成带唯一Guid的Attachment集合 var attachments = targetMails.Select(_ => new Attachment { Id = Guid.NewGuid(), // 客户端生成唯一Guid Filename = fileName, Type = attachmentType, Media = media, LastChangedBy = IdentityHelper.CurrentUserName, LastChangedOn = DateTime.Now, CreatedBy = IdentityHelper.CurrentUserName, CreatedOn = DateTime.Now // 若Attachment与Mail有关联,需补充关联属性,如: Mail = _ }).ToList(); // 3. 批量插入(需确保NHibernate配置了批量插入:如设置adonet.batch_size) Dao.Evaluate(s => { s.SaveOrUpdateAll(attachments); s.Flush(); });
注意事项
- 需在NHibernate配置文件中开启批量插入优化:
<property name="adonet.batch_size">50</property>(数值根据数据量调整) - 此方案会将源Mail数据加载到内存,数据量过大时需注意内存占用。
内容的提问来源于stack exchange,提问作者jodeke
相关产品推荐
相关产品推荐

