@@ -186,6 +186,9 @@ public TValue this[TKey key]
186186 protected SqliteCommand [ ] _deleteItemCommands ;
187187 protected SqliteParameter [ ] _deleteItemIdParameters ;
188188
189+ protected SqliteCommand [ ] _queryIdAndItemCommands ;
190+ protected SqliteParameter [ ] _queryIdAndItemIdParameters ;
191+
189192 protected SqliteCommand [ ] _queryItemCommands ;
190193 protected SqliteParameter [ ] _queryItemIdParameters ;
191194
@@ -297,6 +300,8 @@ public DiskCache(
297300 _upsertItemItemParameters = new SqliteParameter [ DegreeOfParallelism ] ;
298301 _deleteItemCommands = new SqliteCommand [ DegreeOfParallelism ] ;
299302 _deleteItemIdParameters = new SqliteParameter [ DegreeOfParallelism ] ;
303+ _queryIdAndItemCommands = new SqliteCommand [ DegreeOfParallelism ] ;
304+ _queryIdAndItemIdParameters = new SqliteParameter [ DegreeOfParallelism ] ;
300305 _queryItemCommands = new SqliteCommand [ DegreeOfParallelism ] ;
301306 _queryItemIdParameters = new SqliteParameter [ DegreeOfParallelism ] ;
302307 _countItemsCommands = new SqliteCommand [ DegreeOfParallelism ] ;
@@ -360,14 +365,21 @@ public DiskCache(
360365 _upsertItemCommands [ i ] . Prepare ( ) ;
361366
362367 _deleteItemCommands [ i ] = _connections [ i ] . CreateCommand ( ) ;
363- _deleteItemCommands [ i ] . CommandText = $ "DELETE FROM items WHERE id = @id;";
368+ _deleteItemCommands [ i ] . CommandText = $ "DELETE FROM items WHERE id = @id RETURNING item ;";
364369 _deleteItemIdParameters [ i ] = new SqliteParameter ( "@id" , _keyType ) ;
365370 _deleteItemCommands [ i ] . Parameters . Add ( _deleteItemIdParameters [ i ] ) ;
366371 _deleteItemCommands [ i ] . Transaction = _transactions [ i ] ;
367372 _deleteItemCommands [ i ] . Prepare ( ) ;
368373
374+ _queryIdAndItemCommands [ i ] = _connections [ i ] . CreateCommand ( ) ;
375+ _queryIdAndItemCommands [ i ] . CommandText = $ "SELECT id, item FROM items WHERE id = @id;";
376+ _queryIdAndItemIdParameters [ i ] = new SqliteParameter ( "@id" , _keyType ) ;
377+ _queryIdAndItemCommands [ i ] . Parameters . Add ( _queryIdAndItemIdParameters [ i ] ) ;
378+ _queryIdAndItemCommands [ i ] . Transaction = _transactions [ i ] ;
379+ _queryIdAndItemCommands [ i ] . Prepare ( ) ;
380+
369381 _queryItemCommands [ i ] = _connections [ i ] . CreateCommand ( ) ;
370- _queryItemCommands [ i ] . CommandText = $ "SELECT id, item FROM items WHERE id = @id;";
382+ _queryItemCommands [ i ] . CommandText = $ "SELECT item FROM items WHERE id = @id;";
371383 _queryItemIdParameters [ i ] = new SqliteParameter ( "@id" , _keyType ) ;
372384 _queryItemCommands [ i ] . Parameters . Add ( _queryItemIdParameters [ i ] ) ;
373385 _queryItemCommands [ i ] . Transaction = _transactions [ i ] ;
@@ -616,17 +628,17 @@ public bool TryGetValue(TKey key, out TValue value)
616628 {
617629 _queryItemIdParameters [ index ] . Value = keyParameterValue ;
618630
619- using SqliteDataReader reader = _queryItemCommands [ index ] . ExecuteReader ( ) ;
631+ object item = _queryItemCommands [ index ] . ExecuteScalar ( ) ;
620632
621- if ( reader . Read ( ) )
633+ if ( item != null )
622634 {
623635 if ( typeof ( TValue ) == typeof ( long ) || typeof ( TValue ) == typeof ( string ) || typeof ( TValue ) == typeof ( byte [ ] ) || typeof ( TValue ) == typeof ( double ) )
624636 {
625- value = ( TValue ) reader . GetValue ( 1 ) ;
637+ value = ( TValue ) item ;
626638 }
627639 else
628640 {
629- byte [ ] serializedValue = ( byte [ ] ) reader . GetValue ( 1 ) ;
641+ byte [ ] serializedValue = ( byte [ ] ) item ;
630642
631643 value = _deserializeValueFunction ( serializedValue ) ;
632644 }
@@ -668,6 +680,23 @@ public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)
668680 }
669681 }
670682
683+ #if NETSTANDARD2_1_OR_GREATER
684+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
685+ public void AddRange ( ReadOnlySpan < KeyValuePair < TKey , TValue > > items )
686+ {
687+ if ( IsReadOnly )
688+ {
689+ throw new InvalidOperationException ( "Modifications are not allowed when opened in read only mode." ) ;
690+ }
691+
692+ for ( int i = 0 ; i < items . Length ; i ++ )
693+ {
694+ KeyValuePair < TKey , TValue > item = items [ i ] ;
695+ Set ( item . Key , item . Value ) ;
696+ }
697+ }
698+ #endif
699+
671700 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
672701 public void AddParallel ( IEnumerable < KeyValuePair < TKey , TValue > > [ ] parallelItems )
673702 {
@@ -685,21 +714,53 @@ public void AddParallel(IEnumerable<KeyValuePair<TKey, TValue>>[] parallelItems)
685714 }
686715
687716 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
688- public void Remove ( TKey key )
717+ public bool Remove ( TKey key )
718+ => Remove ( key , true , out _ ) ;
719+
720+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
721+ public bool Remove ( TKey key , out TValue removedValue )
722+ => Remove ( key , false , out removedValue ) ;
723+
724+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
725+ public bool Remove ( KeyValuePair < TKey , TValue > item )
726+ => Remove ( item . Key , false , out _ ) ;
727+
728+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
729+ public bool Remove ( KeyValuePair < TKey , TValue > item , out TValue removedValue )
730+ => Remove ( item . Key , false , out removedValue ) ;
731+
732+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
733+ public bool Remove ( KeyValuePair < TKey , TValue > item , out KeyValuePair < TKey , TValue > removedItem )
734+ {
735+ removedItem = default ;
736+
737+ if ( Remove ( item . Key , false , out TValue removedValue ) )
738+ {
739+ removedItem = new KeyValuePair < TKey , TValue > ( item . Key , removedValue ) ;
740+ return true ;
741+ }
742+
743+ return false ;
744+ }
745+
746+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
747+ private bool Remove ( TKey key , bool ignoreReturnedValue , out TValue removedValue )
689748 {
690749 if ( IsReadOnly )
691750 {
692751 throw new InvalidOperationException ( "Modifications are not allowed when opened in read only mode." ) ;
693752 }
694753
695- int index = 0 ;
696- object keyParameterValue = null ;
697-
698754 if ( key is null )
699755 {
700756 throw new ArgumentNullException ( nameof ( key ) ) ;
701757 }
702758
759+ removedValue = default ;
760+
761+ int index = 0 ;
762+ object keyParameterValue = null ;
763+
703764 if ( typeof ( TKey ) == typeof ( long ) )
704765 {
705766 if ( key is long longKey )
@@ -714,7 +775,7 @@ public void Remove(TKey key)
714775 {
715776 if ( stringKey . Length == 0 )
716777 {
717- return ;
778+ return false ;
718779 }
719780
720781 index = GetParallelIndex ( stringKey , DegreeOfParallelism ) ;
@@ -727,7 +788,7 @@ public void Remove(TKey key)
727788 {
728789 if ( bytesKey . Length == 0 )
729790 {
730- return ;
791+ return false ;
731792 }
732793 if ( bytesKey . Length > DiskCacheConstants . MaxItemLength )
733794 {
@@ -742,7 +803,7 @@ public void Remove(TKey key)
742803 {
743804 if ( _serializeKeyFunction is null )
744805 {
745- return ;
806+ return false ;
746807 }
747808
748809 byte [ ] serializedKey = _serializeKeyFunction ( key )
@@ -765,51 +826,28 @@ public void Remove(TKey key)
765826 {
766827 _deleteItemIdParameters [ index ] . Value = keyParameterValue ;
767828
768- _deleteItemCommands [ index ] . ExecuteNonQuery ( ) ;
769- }
770- }
829+ object removedItem = _deleteItemCommands [ index ] . ExecuteScalar ( ) ;
771830
772- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
773- public void Remove ( IEnumerable < TKey > keys )
774- {
775- if ( keys is null )
776- {
777- throw new ArgumentNullException ( nameof ( keys ) ) ;
778- }
779-
780- foreach ( TKey key in keys )
781- {
782- Remove ( key ) ;
783- }
784- }
785-
786- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
787- public void Remove ( KeyValuePair < TKey , TValue > item )
788- {
789- if ( IsReadOnly )
790- {
791- throw new InvalidOperationException ( "Modifications are not allowed when opened in read only mode." ) ;
792- }
793-
794- Remove ( item . Key ) ;
795- }
796-
797- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
798- public void Remove ( IEnumerable < KeyValuePair < TKey , TValue > > items )
799- {
800- if ( items is null )
801- {
802- throw new ArgumentNullException ( nameof ( items ) ) ;
803- }
831+ if ( removedItem is null )
832+ {
833+ return false ;
834+ }
835+ if ( ignoreReturnedValue )
836+ {
837+ return true ;
838+ }
804839
805- if ( IsReadOnly )
806- {
807- throw new InvalidOperationException ( "Modifications are not allowed when opened in read only mode." ) ;
808- }
840+ if ( typeof ( TValue ) == typeof ( long ) || typeof ( TValue ) == typeof ( string ) || typeof ( TValue ) == typeof ( byte [ ] ) || typeof ( TValue ) == typeof ( double ) )
841+ {
842+ removedValue = ( TValue ) removedItem ;
843+ }
844+ else
845+ {
846+ byte [ ] serializedValue = ( byte [ ] ) removedItem ;
809847
810- foreach ( KeyValuePair < TKey , TValue > item in items )
811- {
812- Remove ( item . Key ) ;
848+ removedValue = _deserializeValueFunction ( serializedValue ) ;
849+ }
850+ return true ;
813851 }
814852 }
815853
@@ -826,7 +864,7 @@ public void RemoveParallel(IEnumerable<TKey>[] parallelKeys)
826864 throw new InvalidOperationException ( "Modifications are not allowed when opened in read only mode." ) ;
827865
828866 }
829- parallelKeys . DoParallel ( Remove ) ;
867+ parallelKeys . DoParallel ( key => Remove ( key ) ) ;
830868 }
831869
832870 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
@@ -988,6 +1026,12 @@ public virtual void Dispose()
9881026 _deleteItemCommands [ i ] = null ;
9891027 }
9901028
1029+ if ( _queryIdAndItemCommands is not null && _queryIdAndItemCommands [ i ] is not null )
1030+ {
1031+ _queryIdAndItemCommands [ i ] . Dispose ( ) ;
1032+ _queryIdAndItemCommands [ i ] = null ;
1033+ }
1034+
9911035 if ( _queryItemCommands is not null && _queryItemCommands [ i ] is not null )
9921036 {
9931037 _queryItemCommands [ i ] . Dispose ( ) ;
@@ -1041,6 +1085,7 @@ public virtual void Dispose()
10411085
10421086 _upsertItemCommands = null ;
10431087 _deleteItemCommands = null ;
1088+ _queryIdAndItemCommands = null ;
10441089 _queryItemCommands = null ;
10451090 _countItemsCommands = null ;
10461091 _clearItemsCommands = null ;
0 commit comments