So, a couple things:
- The inline docs say that ExpectedVersion.EmptyStream should equal 0 but it’s actually -1 which is the same as ExpectedVersion.NoStream
Not sure if that’s on purpose or if it’s a bug.
AppendToStreamAsync can take one or more EventDatas but asks for a single expected version. My case right now attempts to save a few events for a new entity so it’s a new stream of Survey-. What I did was set the expected version like this:
var expectedVersion = first.Version == 0
? ExpectedVersion.NoStream
: first.Version;
``
My reasoning is that if it’s event 0, then it’s a new stream, thus should not exist. I’m also assuming that it’s checking this version against the first EventData in the stream I’m saving. I’m getting WrongExpectedVersionException, but when I look at the event store browser, the stream was created and has a single event.
I feel like I need some clarification on how this is supposed to work.
NoStream vs 0 are slightly different. Try setting metadata first and
they will have differing behaviour.
EG
0 no metadata = both work
0 with metadata 0 works not nostream
stream exists = both fail
Not quite sure what you mean by setting the metadata “first”. All of my events have the metadata set in a base class, then when I convert that object to an EventData object, I just pass the metadata in as an argument.
private async Task AppendEventsAsync(string streamName, params EventInfo[] infos)
{
if (string.IsNullOrEmpty(streamName))
throw new ArgumentNullException(nameof(streamName));
if (infos == null || !infos.Any())
throw new ArgumentNullException(nameof(infos));
var first = infos[0];
if (infos.Any(i => i.EntityId != first.EntityId))
throw new InvalidOperationException(“All events in this transaction must belong to the same entity.”);
var stream = infos
.Select(info => new EventData(
info.EventId,
info.EventType,
true,
info.GetData(),
info.Metadata.GetData()))
.ToArray();
var expectedVersion = first.Version == 0
? ExpectedVersion.NoStream
: first.Version;
try
{
await _connection
.AppendToStreamAsync(streamName, expectedVersion, stream)
.ConfigureAwait(false);
}
catch (WrongExpectedVersionException ex)
{
var dirtyStreamEx = new DirtyStreamException(
$"Expected version {expectedVersion}, but the current version was different. " +
"This happens when the stream was modified by some other process before this " +
“process was able to complete (concurrency)”, ex);
throw dirtyStreamEx;
}
}
``
stream metadata such as $maxAge/$maxCount etc
So if I’m understanding you right, then if I never set the stream metadata, then either 0 or NoStream should work? I’m not setting the stream metadata but NoStream is not working, so I’m still confused.
There is a special use case here involving NoStream. You can "created"
a stream by setting an ACL etc which requires a distinction between
this case and 0. EG I can specify "only do this write providing the
stream does not exist". A stream with metadata set is an empty stream
(no items) not a non-existing stream. A vocbulary different would
likely help
Ok so I removed that line completely and let it just pass in the actual version (0) and it’s still giving the same error. The stream metadata is still empty. I also tried NoStream and got the same error. It’s also still writing to the stream despite the exception.
Correction, I used EmptyStream, not NoStream
I think what’s really going on here is that I don’t know the difference between an event version and a stream version. I thought the check was supposed to make sure the new events being written are equal to the last event version + 1. But now I’m thinking this has nothing to do with the event and everything to do with the stream and I don’t quite understand when or why the stream version would change particularly when mine doesn’t even have any metadata
I tend to think of it as ‘whats the version of the last event written?’ So current min - 1.
That appears to not be true though. The last event written was 0, but the stream’s metadata doesn’t even have an entry in it and it still throws errors when I send expected version = 0
if there is an event expected version should be 1 (that is the version
the event will be)
So if my aggregate is retrieved/replayed and the last event is 6 and I add two more events (what would be 7 and 8), when I go to write to the stream, then expected version is 7?
yes as that is the expected version.
Ok I’ll try that. I probably sound dense, but for whatever reason I thought expected version meant “I expect that last version you have is x” vs. “The next version number would be x”
When I get back to it to try it out, I’ll report back to confirm we’re back on the same page
That has been my understanding as well. But maybe I’ve done the same off by one error on all implementations.