Skip to main content

Migration: previous-versions breaking changes

RavenDB 7.0 client breaking changes

Subscription creation overload modification

  • In RavenDB versions earlier than 7.0, the Create<T> method overload that accepted a predicate also allowed specifying a query through SubscriptionCreationOptions, which could cause errors and confusion.
  • To eliminate this ambiguity, starting from 7.0, the Create<T> overload for predicate-based subscriptions now accepts PredicateSubscriptionCreationOptions, which no longer includes a Query property.
  • Refer to the Subscription creation API overview for the complete list of available Create method overloads.
// The create overload using a predicate:
// ======================================
string Create<T>(Expression<Func<T, bool>> predicate = null,
PredicateSubscriptionCreationOptions options = null,
string database = null);

Task<string> CreateAsync<T>(Expression<Func<T, bool>> predicate = null,
PredicateSubscriptionCreationOptions options = null,
string database = null,
CancellationToken token = default);

// The options class:
// ==================
public sealed class PredicateSubscriptionCreationOptions
{
public string Name { get; set; }
public string ChangeVector { get; set; }
public string MentorNode { get; set; }
public bool Disabled { get; set; }
public bool PinToMentorNode { get; set; }
public ArchivedDataProcessingBehavior? ArchivedDataProcessingBehavior { get; set; }
}

HTTP-Compression algorithm is now Zstd by default

From RavenDB 7.0 on, the default HTTP compression algorithm is Zstd (instead of Gzip, used in earlier versions).

Clients can switch to a different HTTP-Compression algorithm using DocumentStore's DocumentConventions.HttpCompressionAlgorithm convention.

var DocumentConventions = new DocumentConventions
{
// Switch HTTP compression algorithm
HttpCompressionAlgorithm = HttpCompressionAlgorithm.Gzip
};

If you migrate from an earlier RavenDB version to version 7.0 or higher,
please note the potential significance of this change.

Bulk-insert Compression is now Enabled by default

Compression is now Enabled by default for bulk-insert operations.

CompressionLevel DefaultCompressionLevel = CompressionLevel.Fastest;

Clients can switch to a different bulk-insert compression state using Store's BulkInsertOptions.CompressionLevel option.

using (var bulk = store.BulkInsert(new BulkInsertOptions
{
// Disable bulk-insert compression
CompressionLevel = CompressionLevel.NoCompression
}));

Removed irrelevant SingleNodeBatchCommand parameters

We removed from SingleNodeBatchCommand's definition the parameters that are mainly used internally and kept only those relevant to the user.

public SingleNodeBatchCommand
(DocumentConventions conventions,
IList<ICommandData> commands,
BatchOptions options = null)

Removed obsolete methods

The following methods are no longer used and have been removed from RavenDB 7.0.

  • NextPageStart

    public int NextPageStart { get; set; }
  • GenerateEntityIdOnTheClient

    public GenerateEntityIdOnTheClient(DocumentConventions conventions,
    Func<object, string> generateId)
  • InMemoryDocumentSessionOperations.GenerateId

    protected override string GenerateId(object entity)
  • InMemoryDocumentSessionOperations.GetOrGenerateDocumentIdAsync

    protected async Task<string> GetOrGenerateDocumentIdAsync(object entity)

FromEtl is now internal

The CounterBatch class FromEtl property is now internal.
FromEtl is used internally to get or set a value indicating whether a counters batch originated from an ETL process.

RavenDB 6.2 client breaking changes

CounterBatchOperation default increment Delta is 1

When CounterBatchOperation is called to Increment a batch of counters, and no Delta is specified to indicate what value should be added to the counters, the operation will increment the counters by a default Delta.

  • Previous RavenDB versions set a default Delta of 0, leaving the counters value unchanged.
  • Starting RavenDB 6.2 the default Delta is 1 to make it consistent with the rest of the API.
var operationResult = store.Operations.Send(new CounterBatchOperation(new CounterBatch
{
Documents = new List<DocumentCountersOperation>
{
new DocumentCountersOperation
{
DocumentId = "users/1",
Operations = new List<CounterOperation>
{
new CounterOperation
{
Type = CounterOperationType.Increment,
CounterName = "likes",
Delta = 5
},
new CounterOperation
{
// No delta specified, value will be incremented by 1
Type = CounterOperationType.Increment,
CounterName = "dislikes"
}
}
}
}
}));

CmpXchg item can only be created with an index of 0

Creating a compare exchange item using PutCompareExchangeValueOperation is now possible only if the index parameter passed to the method is 0.

// Creating the item will fail because the index is not 0
CompareExchangeResult<string> compareExchangeResult
= store.Operations.Send(
new PutCompareExchangeValueOperation<string>("key", "value", 123));

// Creating the item will succeed because the index is 0
compareExchangeResult = store.Operations.Send(
new PutCompareExchangeValueOperation<string>("key", "value", 0));

Dynamic Linq query cannot apply .Any with logical AND (&&)

RavenDB does not support dynamic Linq queries (i.e. queries executed over auto indexes) when they attempt to apply multiple conditions using the .Any method with a logical AND (&&).
The below query, for example, is not supported.

using (var store = new DocumentStore())
{
var guestsCarryingSmallSilverSuitcases = session.Query<Guest>()
// Applying .Any with && is not supported
.Where(x => x.Suitcase.Any(p => p.Size == "Small" && p.Color == "Silver"))
.ToList();
}

While auto indexes do not currently support this type of query, static indexes do.
You can define a static fanout index that creates separate index entries for different document sub-objects, and run your query over these entries.
Read about the indexing of nested data here,
and find explanations and samples for fanout indexes here.

LoadDocument must be provided with a collection name String

When LoadDocument is used in an index query to load related documents, it is passed a document ID and a collection name.

The collection name must be passed to LoadDocument as a regular string; attempting to pass it a dynamic expression instead of a string will fail with an IndexCompilationException exception and this message: LoadDocument method has to be called with constant value as collection name

The following query, for example, will fail because it attempts to build the collection name dynamically.

from doc in docs.Orders
select new {
// This attempt to construct a collection name will fail with an exception
CompanyName = LoadDocument(doc.Company, doc.Company.Split('/')[0]).Name
}

Note that the validation of the collection name string will be forced only during the creation of a new index. An attempt to update an existing index with a collection name expression rather than a string will fail but the failure will remain unnoticed and an exception will not be thrown.

Tracking operations using the Changes API now requires Node Tag

Tracking operations using the changes API now requires that you pass the changes API both a database name and a node tag for the specific node that runs the operation/s you want to track, to ensure that the API consistently tracks this selected node.

The changes API can be opened using two Changes overloads. The first passes the API only the database name and is capable of tracking all entities besides operations. Attempting to track operations after opening the API this way will fail with an ArgumentException exception and the following message:
"Changes API must be provided a node tag in order to track node-specific operations."

To track operations, open the API using this overload:

ISingleNodeDatabaseChanges Changes(string database, string nodeTag);

Then, you can use ForOperationId or ForAllOperations to track a certain operation or all the operations executed by the selected node. Here's a simple usage example:

IDisposable subscription = store
.Changes(database, nodeTag)
.ForOperationId(operationId)
.Subscribe(
change =>
{
switch (change.State.Status)
{
case OperationStatus.InProgress:
//Do Something
break;
case OperationStatus.Completed:
//Do Something
break;
case OperationStatus.Faulted:
//Do Something
break;
case OperationStatus.Canceled:
//Do Something
break;
default:
throw new ArgumentOutOfRangeException();
}
});

Consistency in null handling

IAsyncDocumentSession.LoadAsync and IAsyncLazySessionsOperations.LoadAsync now do not throw an exception when they are passed null, becoming consistent with the behavior of the majority of RavenDB's methods.

// This will work without issues
IAsyncDocumentSession.LoadAsync(null)

RavenDB 6.0 client breaking changes

6.0 Breaking changes

  • Include from a non-tracking session

    • A non-tracking session will now throw an exception if an Include operation is used in it.
    • Like other entities in a NoTracking session, included items are not tracked and will not prevent additional server requests during subsequent Load operations for the same data. To avoid confusion, Include operations are disallowed during non-tracking session actions such as Load or Query.
    • Learn more in Using 'Include' in a NoTracking session will throw.
  • Type changes
    Many methods related to paging information (Skip, Take, PageSize, TotalResults, etc.) that used the int type in former RavenDB versions now use long, e.g. QueryStatistics.TotalResults.

  • Indexing
    The default value of the Indexing.OrderByTicksAutomaticallyWhenDatesAreInvolved configuration option is now true.

  • Facets
    FacetOptions were removed from RangeFacet.

  • Obsolete entities removed
    Many obsolete attributes, properties, and methods were removed from the public API.

  • Certificate disposal
    The DisposeCertificate convention has been introduced to prevent or allow the disposal of DocumentStore.Certificate when the store is disposed, helping users mitigate the X509Certificate2 leak.

  • Serialization
    Only Public fields are serialized/deserialized when projecting query results.
    Private fields are not serialized/deserialized.

  • HiLo ID generator
    DefaultAsyncHiLoIdGenerator is replaced with AsyncHiLoIdGenerator

    public AsyncHiLoIdGenerator(string tag, DocumentStore store, string dbName, char identityPartsSeparator)

6.0 Breaking changes in a sharded database

Unsupported features:

RavenDB 6.0 introduces sharding.
Features that are currently unavailable under a sharded database (but remain available in regular databases) are listed in the sharding unsupported features page.
Attempting to use these features when the database is sharded will normally throw a NotSupportedInShardingException exception.

Casting smuggler results:

The result sets returned by Smuggler and features that use it (import, export, Backup and Restore) are sharding-specific and should not be cast to a non-sharded type.

For example, the following code will fail when the database is sharded.

var operation = await store.Maintenance.SendAsync(new BackupOperation(config));
var result = await operation.WaitForCompletionAsync(TimeSpan.FromSeconds(60));

// This will fail with a sharded database
var backupResult = (BackupResult)result;

For the code to succeed, replace the last line with:

{`var backupResult = (ShardedBackupResult)result;
  • For Backup: ShardedBackupResult
  • For Restore: ShardedRestoreResult
  • For Smuggler, Import, and Export: ShardedSmugglerResult

Endpoints:

  • GET /databases/*/revisions/bin
    Pass start instead of etag.
    We now fetch from the last entry backward rather than from a specific etag.

    GetRevisionsBinEntryCommand
    Previous definition: GetRevisionsBinEntryCommand(long etag, int? pageSize)
    Current definition: GetRevisionsBinEntryCommand(int start, int? pageSize)

  • GET /databases/*/indexes/terms
    The Terms field of the returned results is now List<String> instead of HashSet<String>.

    public class TermsQueryResult
    {
    public List<string> Terms { get; set; }
    public long ResultEtag { get; set; }
    public string IndexName { get; set; }
    }
  • GET database/*/debug/documents/get-revisions
    Operation parameter changed from etag to start.

In this article