Πέρα από την απάντηση του Παναγιώτη, υποθέτω ότι έστω και αν αντιμετωπίσεις το out of memory exception, το μηχάνημα που θα τρέχει την εφαρμογή σου
δεν μπορεί να είναι κάποιο "casual" PC αλλά σίγουρα κάποιος server. ΑΝ υπολογίσεις και το πόσοι θα συνδέονται γιά να πάρουν κάποια από αυτά τα δεδομένα θα αντιμετωπίσεις πολύ μεγαλύτερα προβλήματα.
Από το framework 4.5 και μετά σε 64 bit build υπάρχει μεν το όριο σε array size των 2 giga κλπ αλλά δεν υπάρχουν τέτοιοι περιορισμοί χρησιμοποιώντας την παράμετρο gcallowverylargeobjects στο configuration file
που είχα αναφέρει στο προηγούμενο post που έκανες.
Remarks
Using this element in your application configuration file enables arrays that are larger than 2 GB in size, but does not change other limits on object size or array size:
The maximum number of elements in an array is UInt32.MaxValue.
The maximum index in any single dimension is 2,147,483,591 (0x7FFFFFC7) for byte arrays and arrays of single-byte structures, and 2,146,435,071 (0X7FEFFFFF) for other types.
The maximum size for strings and other non-array objects is unchanged.
Παρόλα αυτά η διαχείρηση μνήμης σε .net με τόσο μεγάλο όγκο δεδομένων από τον Garbage Collector θα σε κάνει να χτυπάς το κεφάλι σου αφού
ο GC δυστυχώς δεν έχει σχεδιαστεί από την αρχή του .NET γιά να αντιμετωπίσει τέτοια προβλήματα.
Στο post https://blogs.msdn.microsoft.com/joshwil/2005/08/10/bigarrayt-getting-around-the-2gb-array-size-limit/
ο κώδικας που του BigArray δεν δουλεύει αλλά τον άλλαξα γιά να μπορείς να τον χρησιμοποιήσεις, χωρίς περιορισμούς framework ή 64 bit
η ακόμα καλύτερα να τον τον επεκτείνεις σε BigList<T>.
Σπάει απλά το size του array σε blocks και στο τελευταίο block βάζει τα elements που περρισεύουν (αν υπάρχουν)
χρησιμοποιώντας την elementsInLastBlock και μετά με τον indexer κάνει partition το κάθε element στην θέση που πρέπει.
Επιμένω στην χρήση Database γιά τέτοια σενάρια αφού ο SQL Server δεν είναι γραμμένος σε .NET και
δεν υπόκειται σε τέτοιους περιορισμούς ή φτιάξε ένα dll σε C++/CLI ή όπως αλλιώς λέγεται τώρα γιά να κάνεις την δουλεία σου.
/// <summary>
/// https://blogs.msdn.microsoft.com/joshwil/2005/08/10/bigarrayt-getting-around-the-2gb-array-size-limit/
/// </summary>
/// <typeparam name="T"></typeparam>
class BigArray<T>
{
// These need to be const so that the getter/setter get inlined by the JIT into
// calling methods just like with a real array to have any chance of meeting our
// performance goals.
//
// BLOCK_SIZE must be a power of 2, and we want it to be big enough that we allocate
// blocks in the large object heap so that they don’t move.
internal const int BLOCK_SIZE = 524288; // 2 ^ 19
internal const int BLOCK_SIZE_LOG2 = 19; // Raise 2 in 19th power to get Block Size.
// Don’t use a multi-dimensional array here because then we can’t right size the last
// block and we have to do range checking on our own and since there will then be
// exception throwing in our code there is a good chance that the JIT won’t inline.
T[][] _elements;
ulong _length;
// maximum BigArray size = BLOCK_SIZE * Int.MaxValue
public BigArray(ulong size)
{
int numBlocks = (int)(size / BLOCK_SIZE);
int elementsInLastBlock = BLOCK_SIZE;
int diff = (int)(size - (ulong)(numBlocks * BLOCK_SIZE));
if (diff > 0)
{
elementsInLastBlock = diff;
numBlocks += 1;
}
_length = size;
_elements = new T[numBlocks][];
// do not assign BLOCK_SIZE to last element (that's why we loop until (numBlocks -1))
// instead assign it after the for loop with
// elementsInLastBlock value.
for (int i = 0; i < (numBlocks -1); i++)
_elements
= new T[BLOCK_SIZE];
// Since Elements is a jagged array,
// the last element can be smaller than BLOCK_SIZE.
_elements[numBlocks - 1] = new T[elementsInLastBlock];
}
public ulong Length { get { return _length; } }
public T this[ulong elementNumber]
{
// these must be _very_ simple in order to ensure that they get inlined into
// their caller
get
{
int blockNum = (int)(elementNumber >> BLOCK_SIZE_LOG2);
int elementNumberInBlock = (int)(elementNumber & (BLOCK_SIZE - 1));
return _elements[blockNum][elementNumberInBlock];
}
set
{
int blockNum = (int)(elementNumber >> BLOCK_SIZE_LOG2);
int elementNumberInBlock = (int)(elementNumber & (BLOCK_SIZE - 1));
_elements[blockNum][elementNumberInBlock] = value;
}
}
}