# Reading from a stream

When using EventStoreDB it's possible to read events from a given stream.

# Reading forwards

The simplest way to read a stream forwards is to supply a stream name, direction and revision to start from. This can either be a stream position Start or a an big int (unsigned 64 bit integer):

    var events = client.ReadStreamAsync(
    	Direction.Forwards,
    	"some-stream",
    	StreamPosition.Start);
    ReadStreamOptions options = ReadStreamOptions.get()
            .forwards()
            .fromStart();
    
    ReadResult result = client.readStream("some-stream", options)
            .get();
    
    List<ResolvedEvent> events = result.getEvents();
    const events = await client.readStream("some-stream", {
      direction: FORWARDS,
      fromRevision: START,
      maxCount: 10,
    });
    let options = ReadStreamOptions::default()
        .position(StreamPosition::Start)
        .forwards();
    let result = client.read_stream("some-stream", &options, All).await?;
    // Make sure to add code blocks to your code group

    This will return an enumerable that can be iterated on:

      await foreach (var @event in events) {
      	Console.WriteLine(Encoding.UTF8.GetString(@event.Event.Data.ToArray()));
      }
      for (ResolvedEvent resolvedEvent : events) {
          RecordedEvent recordedEvent = resolvedEvent.getOriginalEvent();
          System.out.println(new ObjectMapper().writeValueAsString(recordedEvent.getEventData()));
      }
      for (var resolvedEvent of events) {
        console.log(resolvedEvent.event.data);
      }
      if let Some(mut events) = result.ok() {
          while let Some(event) = events.try_next().await? {
              let test_event = event.get_original_event().as_json::<TestEvent>()?;
      
              println!("Event> {:?}", test_event);
          }
      }
      // Make sure to add code blocks to your code group

      There are a number of additional arguments you can provide when reading a stream

      # maxCount

      Passing in the max count allows you to limit the number of events that returned.

      # resolveLinkTos

      When using projections to create new events you can set whether the generated events are pointers to existing events. Setting this value to true will tell EventStoreDB to return the event as well as the event linking to it.

      # configureOperationOptions

      This argument is generic setting class for all operations that can be set on all operations executed against EventStoreDB.

      # userCredentials

      The credentials used to read the data can be supplied. to be used by the subscription as follows. This will override the default credentials set on the connection.

        var result = client.ReadStreamAsync(
        	Direction.Forwards,
        	"some-stream",
        	StreamPosition.Start,
        	userCredentials: new UserCredentials("admin", "changeit"),
        	cancellationToken: cancellationToken);
        UserCredentials credentials = new UserCredentials("admin", "changeit");
        
        ReadStreamOptions options = ReadStreamOptions.get()
                .forwards()
                .fromStart()
                .authenticated(credentials);
        
        ReadResult result = client.readStream("some-stream", options)
                .get();
        const credentials = {
          username: "admin",
          password: "changeit",
        };
        const events = await client.readStream("some-stream", {
          direction: FORWARDS,
          fromRevision: START,
          credentials,
          maxCount: 10,
        });
        let options = ReadStreamOptions::default()
            .position(StreamPosition::Start)
            .authenticated(Credentials::new("admin", "changeit"));
        
        let result = client.read_stream("some-stream", &options, All).await?;
        // Make sure to add code blocks to your code group

        # Reading from a revision

        As well as providing a StreamPosition you can also provide a specific stream revision in the form of a big int (unsigned 64 bit integer).

          var events = client.ReadStreamAsync(
          	Direction.Forwards,
          	"some-stream",
          	revision: 10,
          	maxCount: 20);
          ReadStreamOptions options = ReadStreamOptions.get()
                  .forwards()
                  .fromRevision(10);
          
          ReadResult result = client.readStream("some-stream", 20, options)
                  .get();
          
          List<ResolvedEvent> events = result.getEvents();
          const events = await client.readStream("some-stream", {
            direction: FORWARDS,
            fromRevision: BigInt(10),
            maxCount: 20,
          });
          let options = ReadStreamOptions::default().position(StreamPosition::Point(10));
          let result = client.read_stream("some-stream", &options, 20).await?;
          // Make sure to add code blocks to your code group

          # Reading backwards

          As well as being able to read a stream forwards you can also go backwards. When reading backwards is the stream position will have to be set to the end if you want to read all the events:

            var events = client.ReadStreamAsync(
            	Direction.Backwards,
            	"some-stream",
            	StreamPosition.End);
            
            await foreach (var e in events) {
            	Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray()));
            }
            ReadStreamOptions options = ReadStreamOptions.get()
                    .backwards()
                    .fromEnd();
            
            ReadResult result = client.readStream("some-stream", options)
                    .get();
            
            List<ResolvedEvent> events = result.getEvents();
            
            for (ResolvedEvent resolvedEvent : events) {
                RecordedEvent recordedEvent = resolvedEvent.getOriginalEvent();
                System.out.println(new ObjectMapper().writeValueAsString(recordedEvent.getEventData()));
            }
            const events = await client.readStream("some-stream", {
              direction: BACKWARDS,
              fromRevision: END,
              maxCount: 10,
            });
            
            for (var resolvedEvent of events) {
              console.log(resolvedEvent.event.data);
            }
            let options = ReadStreamOptions::default()
                .position(StreamPosition::End)
                .backwards();
            let result = client.read_stream("some-stream", &options, All).await?;
            
            if let Some(mut events) = result.ok() {
                while let Some(event) = events.try_next().await? {
                    let test_event = event.get_original_event().as_json::<TestEvent>()?;
            
                    println!("Event> {:?}", test_event);
                }
            }
            // Make sure to add code blocks to your code group

            TIP

            You can use reading backwards to find the last position in the stream. Just read backwards one event and get the position.

            # Checking for stream presence

            Reading a stream returns a ReadStreamResult this contains a property ReadState. This property can have the value StreamNotFound and Ok.

            It is important to check the value of this field before attempting to iterate an empty stream as it will throw an exception. For example.

              var result = client.ReadStreamAsync(
              	Direction.Forwards,
              	"some-stream",
              	revision: 10,
              	maxCount: 20);
              
              if (await result.ReadState == ReadState.StreamNotFound) {
              	return;
              }
              
              await foreach (var e in result) {
              	Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray()));
              }
              ReadStreamOptions options = ReadStreamOptions.get()
                      .forwards()
                      .fromRevision(10);
              
              List<ResolvedEvent> events = null;
              try {
                  ReadResult result = client.readStream("some-stream", 20, options)
                          .get();
                  events = result.getEvents();
              } catch (ExecutionException e) {
                  Throwable innerException = e.getCause();
              
                  if (innerException instanceof StreamNotFoundException) {
                      return;
                  }
              }
              
              for (ResolvedEvent resolvedEvent : events) {
                  RecordedEvent recordedEvent = resolvedEvent.getOriginalEvent();
                  System.out.println(new ObjectMapper().writeValueAsString(recordedEvent.getEventData()));
              }
              let events = [];
              try {
                events = await client.readStream("some-stream", {
                  direction: FORWARDS,
                  fromRevision: BigInt(10),
                  maxCount: 20,
                });
              } catch (error) {
                if (error.type == ErrorType.STREAM_NOT_FOUND) return;
              
                throw error;
              }
              
              for (var resolvedEvent of events) {
                console.log(resolvedEvent.event.data);
              }
              let options = ReadStreamOptions::default().position(StreamPosition::Point(10));
              
              let result = client.read_stream("some-stream", &options, All).await?;
              
              match result {
                  ReadResult::Ok(mut events) => {
                      while let Some(event) = events.try_next().await? {
                          let test_event = event.get_original_event().as_json::<TestEvent>()?;
              
                          println!("Event> {:?}", test_event);
                      }
                  }
              
                  ReadResult::StreamNotFound(stream_name) => {
                      println!("Stream not found: {}", stream_name);
              
                      return Ok(());
                  }
              }
              // Make sure to add code blocks to your code group
              Last Updated: 3/2/2021, 1:16:11 PM