Salvataggio 1000+ record al database in un momento
-
13-09-2019 - |
Domanda
Sto usando NHibernate attualmente. Ho una situazione in cui ho bisogno di salvare un gruppo di record al database in questo modo:
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);
}
Quando ci sono un sacco di record da salvare questo è ovviamente molto tassare dover colpire il database che molte volte. Che cosa è un approccio migliore? C'è una sorta di aggiornamento batch che posso fare? Sono forse meglio utilizzare un DataSet?
Grazie
Soluzione
impostazione adonet.batch_size potrebbe migliorare la situazione.
Per questo è necessario
- impostare adonet.batch_size nella configurazione NH
Esempio:
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();
-
impostare la dimensione del lotto sulla sessione appena prima del salvataggio
using (ISession session = m_nhibernateSessionFactory.GetSession()) using (var tx = session.BeginTransaction()) { session.SetBatchSize(1000); foreach (var server in serverz) { session.SaveOrUpdate(server); } tx.Commit(); }
Altri suggerimenti
Credo che questo è quello che stai cercando:
Bulk I dati di operazioni con NHibernate Stateless Sessions
In sostanza, invece di aprire un ISession, si apre un IStatelessSession, e nel vostro hibernate.cfg.xml è possibile impostare:
<property name="adonet.batch_size">100</property>
Penso che tu abbia un numero di opzioni a seconda della situazione.
Se è possibile utilizzare NHibernate 2.1 alfa si può provare a utilizzare il nuovo eseguibile HQL che è disponibile.
http://nhibernate.info/blog /2009/05/05/nh2-1-executable-hql.html
La risposta di Tobias funziona altrettanto bene. Basta impostare la dimensione del lotto aumenterà la prestazione rispettabile.
Se si vuole sporcare le mani con ADO.Net ...
Fare Inserti di massa in SQL Server è possibile attraverso l'uso di SQL Copia globale.
Un esempio di ciò è qui: http://dotnetslackers.com/articles/ado_net/ SqlBulkCopy_in_ADO_NET_2_0.aspx
A me sembra che si sta creando una nuova entità in base al largo di un'altra entità nel database. A me questo sembra uno scenario ideale per utilizzare una stored procedure.
DataSet? No. Inserimento di massa? Sì.
Se si sta inserendo che molti record e gli inserti sono piuttosto semplicistico, si dovrebbe guardare a fare inserimenti di massa e tirando fuori l'ORM.
Il modo più veloce per inserire i record è quello di generare un file di testo e utilizzare la sintassi FILE LOAD. La maggior parte dei database hanno implementazioni notevolmente veloci per l'importazione di file di dati nei database. Per MySQL, vedere di seguito:
http://dev.mysql.com/doc /refman/5.1/en/load-data.html
Per altri database, fare riferimento al manuale appropriato. Questo è utile se si sta inserendo un milione di dischi, o migliaia di record di frequente. In caso contrario, il meglio che puoi fare è creare un grande SQL con il 1000s di inserti ed eseguire che sulla vostra connessione di database direttamente, ORM saltare e le loro convalide correlati.