Próbuję użyć Fluent NHibernate w celu przeprowadzenia migracji bazy danych wymagającej "masowania" bazy danych. Źródłowa baza danych to baza danych MS Access, a aktualna tabela, na której utknąłem, to jedna z polem OLE Object. Docelowa baza danych to baza danych MS SQL Server Express.Wywołanie wyjątku NHibernate OutOfMemoryException dla dużego bajtu []
w jednostce po prostu musiałem to pole zdefiniowane jako byte[]
jednak podczas ładowania jednak nawet wtedy, gdy po prostu ładuje że pojedyncze pole dla pojedynczego rekordu byłem uderzenie System.OutOfMemoryException
byte[] test = aSession.Query<Entities.Access.Revision>().Where(x => x.Id == 5590).Select(x => x.FileData).SingleOrDefault<byte[]>();
Następnie próbowałem wdrażającego blob type listed here ale teraz, gdy uruchomiony że otrzymam błędu:
„Nie można rzutować obiektu typu«System.Byte []»wpisz «TestProg.DatabaseConverter.Entities.Blob».”}
Nie mogę sobie wyobrazić, że obiekt Ole ma rozmiar większy niż 100 MB, ale nie był w stanie go sprawdzić. Czy jest jakiś dobry sposób korzystania z Fluent NHibernate w celu skopiowania tego z jednej bazy danych i zapisania jej w innym, czy będę musiał przyjrzeć się innym opcjom?
Moja normalna pętla przetwarzania nich to:
IList<Entities.Access.Revision> result;
IList<int> recordIds = aSession.Query<Entities.Access.Revision>().Select(x => x.Id).ToList<int>();
foreach (int recordId in recordIds)
{
result = aSession.Query<Entities.Access.Revision>().Where(x => x.Id == recordId).ToList<Entities.Access.Revision>();
Save(sqlDb, result);
}
Zapisz funkcji wystarczy kopiuje właściwości z jednego do drugiego i dla niektórych jednostek służy do manipulowania danymi lub przekazywać informacje zwrotne do problemów związanych z danymi użytkownika. Używam sesji bezstanowych dla obu baz danych.
-
z dalszego testowania obiektów wydaje się być wiszące na to około 60-70mb. Obecnie testuję pobieranie danych za pomocą OleDbDataReader przy użyciu GetBytes.
-
Update (24 listopada): Mam jeszcze znaleźć sposób, aby uzyskać to do pracy z NHibernate. Zrobiłem to działając z normalnymi obiektami poleceń db. Umieściłem kod funkcji, którą zrobiłem poniżej, dla każdego, kto jest ciekawy, kto to znajdzie. Jest to kod z mojego konwertera bazy danych, więc obiekty z prefiksem "a" są obiektami bazy danych dostępu, a 's' są obiektami sql.
public void MigrateBinaryField(int id, string tableName, string fieldName)
{
var aCmd = new OleDbCommand(String.Format(@"SELECT ID, {0} FROM {1} WHERE ID = {2}", fieldName, tableName, id), aConn);
using (var reader = aCmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
if (reader[fieldName] == DBNull.Value)
return;
long read = 0;
long offset = 0;
// Can't .WRITE a NULL column so need to set an initial value
var sCmd = new SqlCommand(string.Format(@"UPDATE {0} SET {1} = @data WHERE OldId = @OldId", tableName, fieldName), sConn);
sCmd.Parameters.AddWithValue("@data", new byte[0]);
sCmd.Parameters.AddWithValue("@OldId", id);
sCmd.ExecuteNonQuery();
// Incrementally store binary field to avoid OutOfMemoryException from having entire field loaded in memory
sCmd = new SqlCommand(string.Format(@"UPDATE {0} SET {1}.WRITE(@data, @offset, @len) WHERE OldId = @OldId", tableName, fieldName), sConn);
while ((read = reader.GetBytes(reader.GetOrdinal(fieldName), offset, buffer, 0, buffer.Length)) > 0)
{
sCmd.Parameters.Clear();
sCmd.Parameters.AddWithValue("@data", buffer);
sCmd.Parameters.AddWithValue("@offset", offset);
sCmd.Parameters.AddWithValue("@len", read);
sCmd.Parameters.AddWithValue("@OldId", id);
sCmd.ExecuteNonQuery();
offset += read;
}
}
}
}
Czy próbowałeś tego? https://github.com/bittercoder/Lob – Najera
@Najera Dałem tego strzału i nie działał. Nie pamiętam szczegółów, ale wydaje mi się, że wciąż pamiętam wyjątki od pamięci. Minęło trochę czasu, więc nie w 100%. –
Czy możesz podać nam mapowanie, które wykonałeś? – TedOnTheNet