NHibernateを使用してSQLiteデータベースに一括挿入する必要があります。オブジェクトのPKはHiLoint32です。session.insertでNHステートレスセッションを使用しようとしましたが、正常に動作します。ただし、preparedコマンドを使用すると約30〜40%高速であることがわかったので、それを利用しようとしています。
現在、ID(NH HiLo)の割り当てに苦労しています。stackoverflow(NHibernate HiLo ID Generator。保存する前にIDを生成する)の解決策を見つけました-メソッドGenerateIdentifier()を参照してください。ただし、呼び出しごとにデータベースを照会および更新するため、適切なオプションではありません。
想定どおりに機能させる方法はありますか?idジェネレーターがhivalueに達すると、サーバーへのラウンドトリップを1回だけ実行して、新しいlow値とhi値を取得しますか?
public static Int64 TestNHSQLiteBulk(bool newDB)
{
int ProjectCount = 1000000;
var factory = Database.CreateSQLiteSessionFactory(newDB);
Int64 objectCount = 0;
using (var session = factory.OpenStatelessSession())
{
var connection = session.Connection;
using (var transaction = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
// this should be removed when proper HiLo will be implemented.
var nextProject = session.CreateCriteria<Project>().SetProjection(Projections.Max<Project>(p => p.ProjectId)).UniqueResult();
int startId = (nextProject == null) ? 0 : (int)nextProject + 1;
var command = connection.CreateCommand();
command.CommandText = "Insert INTO Project (ProjectId, ProjectName) Values(?,?)";
var projectIdParameter = command.CreateParameter();
projectIdParameter.ParameterName = "ProjectId";
projectIdParameter.DbType = System.Data.DbType.Int32;
var projectNameParameter = command.CreateParameter();
projectNameParameter.ParameterName = "ProjectName";
projectNameParameter.DbType = System.Data.DbType.String;
command.Parameters.Add(projectIdParameter);
command.Parameters.Add(projectNameParameter);
command.Prepare();
for (int p = startId; p < startId + ProjectCount; p++)
{
var project = new Project()
{
ProjectName = "Project " + p
};
//found on stackoverflow, but is results a roundtrip to server on each call.
GenerateIdentifier(project, Database.savedConfig, session);
//session.Insert(project);
//using prepared command is almost 2x faster!
projectIdParameter.Value = project.ProjectId;
projectNameParameter.Value = project.ProjectName;
command.ExecuteNonQuery();
objectCount++;
}
transaction.Commit();
}
}
return objectCount;
}
//this will get the value and update the hi-lo value repository in the datastore
public static void GenerateIdentifier(object target, NHibernate.Cfg.Configuration conf, IStatelessSession session)
{
var targetType = target.GetType();
var classMapping = conf.GetClassMapping(targetType);
var impl = session.GetSessionImplementation();
var newId = classMapping.Identifier.CreateIdentifierGenerator(impl.Factory.Dialect, classMapping.Table.Catalog, classMapping.Table.Schema,
classMapping.RootClazz).Generate(impl, target);
classMapping.IdentifierProperty.GetSetter(targetType).Set(target, newId);
}