2009-06-11 6 views
10

J'utilise NHibernate actuellement. J'ai une situation où je dois sauver un tas d'enregistrements à la base de données comme ceci:Enregistrement de plus de 1000 enregistrements dans la base de données à la fois

var relatedTopics = GetRelatedTopics(topic); 
foreach (var relatedTopic in relatedTopics /* could be anywhere from 10 - 1000+ */) 
{ 
    var newRelatedTopic = new RelatedTopic { RelatedTopicUrl = relatedTopic, TopicUrl = topic.Name }; 
    _repository.Save(newRelatedTopic); 
} 

Quand il y a une tonne de dossiers pour sauver c'est évidemment très taxant d'avoir à frapper la base de données à plusieurs reprises. Quelle est la meilleure approche? Y at-il une sorte de mise à jour par lots que je peux faire? Suis-je préférable d'utiliser un DataSet?

Merci

+0

J'accepterais la réponse de David P comme solution à la question. –

Répondre

12

mise en adonet.batch_size pourrait améliorer la situation.

Pour que vous devez

  • ensemble adonet.batch_size dans la configuration NH

Exemple:

m_sessionFactory = Fluently 
     .Configure() 
     .Database(MsSqlConfiguration 
      .MsSql2005 
      .ConnectionString(c => c.FromConnectionStringWithKey("testme")) 
      ) 
     .Mappings(m => m.FluentMappings 
      .AddFromAssemblyOf<TestImpl>()) 
     .ExposeConfiguration(config => 
     { 
      config.SetProperty("adonet.batch_size", "1"); 
      m_configuration = config; 
     }) 
     .BuildSessionFactory(); 
  • définir la taille du lot sur la session juste avant le sauver

    using (ISession session = m_nhibernateSessionFactory.GetSession()) 
    using (var tx = session.BeginTransaction()) 
    {  
        session.SetBatchSize(1000);  
        foreach (var server in serverz) 
        { 
         session.SaveOrUpdate(server); 
        } 
        tx.Commit(); 
    } 
    
+0

Pouvez-vous élaborer un peu s'il vous plaît? – Micah

+1

Pourquoi définissez-vous m_configuration? Je reçois toujours une erreur sur SetBatchSize et j'essayais de comprendre pourquoi. J'utilise Oracle, peut-être que cela ne supporte pas la taille de lot ?? –

1

DataSet? No. Insert en vrac? Oui.

Si vous insérez autant d'enregistrements et que les insertions sont plutôt simplistes, vous devriez regarder Bulk Inserts et extraire l'ORM.

+0

Pouvez-vous nous en dire un peu plus? Je n'ai jamais traité avec des insertions en vrac avant. Merci! – Micah

1

Le moyen le plus rapide d'insérer des enregistrements est de générer un fichier texte et d'utiliser la syntaxe LOAD FILE. La plupart des bases de données ont des implémentations remarquablement rapides pour importer des fichiers de données dans les bases de données. Pour MySQL, voir ci-dessous:

http://dev.mysql.com/doc/refman/5.1/en/load-data.html

Pour d'autres bases de données, reportez-vous au manuel approprié. Ceci est utile si vous insérez un million d'enregistrements ou des milliers d'enregistrements fréquemment. Sinon, le mieux que vous puissiez faire est de créer un gros SQL avec les milliers d'insertions et de l'exécuter directement sur votre connexion à la base de données, en ignorant les ORM et leurs validations associées.

3

Je pense que vous avez un certain nombre d'options en fonction de votre situation.

Si vous pouvez utiliser NHibernate 2.1 alphas, vous pouvez essayer d'utiliser le nouveau fichier exécutable HQL disponible.

http://nhibernate.info/blog/2009/05/05/nh2-1-executable-hql.html

réponse de Tobias fonctionnera aussi bien. Le simple réglage de la taille du lot augmentera les performances de manière respectueuse.

Si vous voulez salir les mains avec ADO.Net ...

des insertions en vrac dans Sql Server est possible grâce à l'utilisation de Sql copie en bloc.

Un exemple de ce qui est ici: http://dotnetslackers.com/articles/ado_net/SqlBulkCopy_in_ADO_NET_2_0.aspx

Pour moi, il semble que vous créez une nouvelle entité basée hors d'une autre entité dans la base de données.Pour moi, cela semble être un scénario idéal pour utiliser une procédure stockée.

Questions connexes