/// <summary> /// 为所有的实体生成 Id。 /// </summary> /// <param name="batch"></param> private void GenerateId(EntityBatch batch) { var dba = batch.DBA; var entities = batch.InsertBatch; //如果批量生成 Id 使用的序列号太低,则需要抛出异常。 var seqName = OracleMigrationProvider.SequenceName(batch.Table.Name, batch.Table.IdentityColumn.Name); var incrementBy = Convert.ToInt32(dba.QueryValue("SELECT INCREMENT_BY FROM ALL_SEQUENCES WHERE SEQUENCE_NAME = {0}", seqName)); if (incrementBy < 100) { throw new InvalidOperationException(string.Format("使用批量保存,表 {0} 的序列 {1} 的每次递增数不能少于 100。建议在数据库生成完成后使用 Rafy.Domain.ORM.BatchSubmit.Oracle.OracleBatchImporter.EnableBatchSequence() 来变更序列的每次递增数以启用聚合的批量生成。", batch.Table.Name, seqName)); } //由于每次生成的 Id 号数有限,所以需要分批生成 Id var nextSeqValueSql = string.Format("SELECT {0}.NEXTVAL FROM DUAL", seqName); foreach (var section in EnumerateAllBatches(batch.InsertBatch, incrementBy)) { var nextValue = Convert.ToInt32(dba.QueryValue(nextSeqValueSql)); var startId = nextValue - incrementBy + 1; for (int i = 0, c = section.Count; i < c; i++) { var item = section[i]; item.Id = startId++; } } }
/// <summary> /// 为指定的聚合启用批量插入。 /// 此方法会更改整个聚合中所有实体对应的序列的每次递增数为 sequenceStep。 /// 调用时机:在数据库生成完成后调用。 /// 原因:在 ORACLE 中,如果要批量插入实体,则需要先把实体对应的 Sequence 变为以 sequenceStep 为每次递增。 /// 副作用:这会导致不使用批量插入功能时,实体的 Id 号变为 100000,200000,300000 这样的形式递增。 /// </summary> /// <param name="aggtRepo">The aggt repo.</param> /// <param name="sequenceStep">The sequence step.</param> public static void EnableBatchSequence(IRepository aggtRepo, int sequenceStep = 100000) { if (sequenceStep < 100) { throw new ArgumentOutOfRangeException("sequenceStep"); } using (var dba = RdbDataProvider.Get(aggtRepo).CreateDbAccesser()) { foreach (var repo in DomainHelper.EnumerateAllTypesInAggregation(aggtRepo)) { var table = RdbDataProvider.Get(repo).DbTable; var seqName = OracleMigrationProvider.SequenceName(table.Name, table.IdentityColumn.Name); dba.ExecuteText(string.Format("ALTER SEQUENCE {0} INCREMENT BY {1} NOCACHE", seqName, sequenceStep)); } } }