Header menu logo FCQRS

Read-side

Here we will have one simple function. Every time an event is persisted, it will be sent to the read side. Here you can use whatever you like, be it SQL, Entity Framework, MongoDB, or whatever you like. Make sure you persist the offset value to a table or persistent storage in the same transaction. This is to ensure that if the query side crashes, it can start from the last offset value. You can also use a transaction to commit them atomically. User Flow

open Microsoft.Extensions.Logging
open FCQRS.Common

// All persisted events will come with monotonically increasing offset value.
let handleEventWrapper env (offsetValue: int64) (event:obj)=

        match event with
        | :? FCQRS.Common.Event<User.Event> as  event ->

          // Your SQL statements
          // make sure to update the offset value to a table 
          // or persistent storage in the same transaction.
            [event:> IMessageWithCID]
        |  _ -> []

Finally, we return a list of IMessageWithCID. This is a list of messages that are sent to the read side. Then optionally you can subscribe to these messages. Which will be done in the next section. You can also return something completely custom. Your cross-bounded context event or a DTO like event is preferred.

namespace FCQRS
namespace FCQRS.Model
module Data from FCQRS.Model
module Bootstrap
module Command
namespace Microsoft
namespace Microsoft.Extensions
namespace Microsoft.Extensions.Logging
module Common from FCQRS
<summary> Contains common types like Events and Commands </summary>
<namespacedoc><summary>Functionality for Write Side.</summary></namespacedoc>
val handleEventWrapper: env: 'a -> offsetValue: int64 -> event: obj -> IMessageWithCID list
val env: 'a
val offsetValue: int64
Multiple items
val int64: value: 'T -> int64 (requires member op_Explicit)

--------------------
type int64 = System.Int64

--------------------
type int64<'Measure> = int64
val event: obj
type obj = System.Object
type Event<'EventDetails> = { EventDetails: 'EventDetails CreationDate: DateTime Id: MessageId option Sender: ActorId option CorrelationId: CID Version: Version } interface IMessageWithCID interface ISerializable member Equals: Event<'EventDetails> * IEqualityComparer -> bool override ToString: unit -> string
<summary> Represents an event generated by an aggregate actor as a result of processing a command. &lt;typeparam name="'EventDetails"&gt;The specific type of the event payload.&lt;/typeparam&gt; </summary>
module User
type Event = | LoginSucceeded | LoginFailed | RegisterSucceeded of string * string | AlreadyRegistered member Equals: Event * IEqualityComparer -> bool member IsAlreadyRegistered: bool member IsLoginFailed: bool member IsLoginSucceeded: bool member IsRegisterSucceeded: bool
val event: Event<User.Event>
type IMessageWithCID = abstract CID: CID
<summary> Interface for messages that carry a Correlation ID (CID). </summary>

Type something to start searching.