Migration: Client Breaking Changes


The features listed in this page were available in former RavenDB versions.
In RavenDB 6.2.x, they are either unavailable or their behavior is inconsistent with their behavior in previous versions.


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)

Do you need any help with Migration?