在一个表中查找行,并使用 NHibernate 将其移动到第二个表中

本文关键字:NHibernate 第二个 移动 一个 查找 | 更新日期: 2024-11-06 15:06:00

>我有一个SQL Server 2014数据库,其中包含一个名为Positions的包含大量数据的表(全速可能是数百万行)。Id是主键,此表上没有其他键或外部关系。

假设我有一个n元素的列表,例如[{a1, b1, c1}, ... , {an; bn; cn}],我必须在Positions表内进行搜索并获取所有匹配的行:

(columnA == a1 && columnB == b1 && columnC == c1)
OR 
(columnA == an && columnB == bn && columnC == cn)

此查询可能会产生 0 到 n 行(即没有两行具有相同的{a, b c})生成的行应从Partitions表中删除并插入到名为 DeletedPositions 的第二个表中,并且一切都应以原子方式完成。

我应该在NHibernate

中执行此操作,现在因为我不知道NHibernate:

  1. 我有用于此类操作的设施吗?
  2. 我应该使用 NHibernate 还是批处理 SQL 命令会执行得更好?
  3. 如何确保移动所有(或不移动)行?

这完成了工作,我如何改进它以制作相关的插入?

            var configuration = new Configuration().DataBaseIntegration(db =>
            {
                db.ConnectionString = @"Server=***;Database=***;Uid=***;Pwd=***;";
                db.Dialect<MsSql2008Dialect>();
                db.BatchSize = 700;
            });
            var mapper = new ModelMapper();
            mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
            HbmMapping mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
            configuration.AddMapping(mapping);
            var sessionFactory = configuration.BuildSessionFactory();
            IList<PositionDTO> p = null;
            using (IStatelessSession statelessSession = sessionFactory.OpenStatelessSession()) {
                p = statelessSession
                    .QueryOver<PositionDTO>()
                    .Where(Restrictions.On<PositionDTO>(y => y.ColumnA).IsIn(a))
                    .And(Restrictions.On<PositionDTO>(y => y.ColumnB).IsIn(b))
                    .And(Restrictions.On<PositionDTO>(y => y.ColumnC).IsIn(c))
                    .List<PositionDTO>();

                using (ITransaction transaction = statelessSession.BeginTransaction())
                {
                    foreach (var t in p)
                    {
                        statelessSession.Delete(t);
                    }
                    transaction.Commit();
                }
            }

在一个表中查找行,并使用 NHibernate 将其移动到第二个表中

    使用
  1. NHibernate 时,使用具有足够隔离级别的事务,该事务跨越 HQL insert 查询,后跟delete查询。最好将这些查询命名为在会话工厂引导程序中进行验证,但如果必须动态构造它,请使用"内置代码"HQL 字符串。基本部分示例:
<!-- put that in your .hbm.xml mappings -->
<query name="yourInsertsQuery">
insert into YourTarget
  (
    prop1, prop2, prop3
  )
  select s.propA, sre.propB, ot.propC
    from YourSource s
    inner join s.SomeRelatedEntities sre
      with sre.anythingOnWhichYouHaveAdditionalRestrictions = :someParam
    left join s.OtherThings ot
    where s.someProp = :someOtherParam
      and o.someBooleanCol = false
</query>
// If you required such a high isolation level, so be it, but try
// avoiding it otherwise.
var tran = session.BeginTransaction(IsolationLevel.Serializable);
try
{
    session.GetNamedQuery("yourInsertsQuery")
        .SetParameter("someParam", someValue)
        .SetParameter("someOtherParam", someOtherValue)
        .ExecuteUpdate();
    session.GetNamedQuery("yourDeleteQuery")
        .SetParameter("someParam", someValue)
        .SetParameter("someOtherParam", someOtherValue)
        .ExecuteUpdate();
    tran.Commit()
}
catch
{
    try
    {
        tran.Rollback();
    }
    catch(Exception rollbackEx)
    {
        // better log rollbackEx then swallow it (no throw in this nested catch)
        // to let original trouble bubble up.
    }
    // Let original failure bubble up
    throw;
}
  1. 编辑:实际上,使用SQL不会有太大的性能差异。我正在考虑将 SQL merge用于将两个操作合二为一,但这在您的情况下不可行,因为插入目标与删除目标不同。
    由于从应用到数据库以处理操作的两个调用之间引入了网络延迟,因此你将有一些差异。这将导致事务持续时间稍长,从而可能阻止其他应用程序调用更长。SQL 批处理将避免插入和删除之间的这种额外的网络延迟。
    如果你想要一个 sql 存储过程,你可以使用映射中定义的命名 sql 查询来调用它,如果你愿意:只需使用 <sql-query> ,并使用参数将 SQL exec放入其中,如 hql 示例中所示。
  2. 将您的处理封装在单个事务中。