Why is my command event string field retrieved as null

I am writing my first test application EventStore, I rewet my object from the stream, and while it correctly gets numberSold, the header is NULL, and I don’t understand why - the command when retrieving from stream has a name set to null, but I'm sure that it is written OK.

Can a fresh pair of eyes see what I'm doing wrong?

private static void Main() { using (store = WireupEventStore()) { var newBook = new Book("my book", 0); newBook.ChangeBookName("renamed book"); newBook.AdjustBooksSold(5); var idToRetrieveLater = newBook.bookId; var bookRepo = new BookRepository(store); bookRepo.Put(newBook); var bookReadBack = bookRepo.Get(idToRetrieveLater); // book name is set to null here, but count==5 is OK } 

Book class

 public class Book { public readonly Guid bookId; private int numberSold; private string title { get; set; } private List<object> eventsToCommit = new List<object>(); public Book(string title, int sold) { this.bookId = Guid.NewGuid(); this.title = title; this.numberSold = sold; } public Book(Guid id, IEnumerable<EventMessage> events) { this.bookId = id; foreach (var ev in events) { dynamic @eventToCall = ev.Body; Apply(@eventToCall); } } public void ChangeBookName(string name) { var nameChanged = new BookNameChanged(this.bookId, name); this.RaiseEvent(nameChanged); } public void AdjustBooksSold(int count) { var booksSold = new BookSold(this.bookId, count); this.RaiseEvent(booksSold); } private void Apply(BookNameChanged nameChanged) { this.title = nameChanged.title; } private void Apply(BookSold bookSold) { this.numberSold += bookSold.count; } protected void RaiseEvent(object eventToRaise) { dynamic @ev = eventToRaise; Apply(@ev); this.eventsToCommit.Add(eventToRaise); } public ICollection<object> GetEvents() { return this.eventsToCommit; } public void ResetEvents() { this.eventsToCommit = new List<object>(); } } 

Book repository

 public class BookRepository { IStoreEvents store; public BookRepository(IStoreEvents store) { this.store = store; } public void Put(Book book) { using (var stream = this.store.OpenStream(book.bookId, 0, int.MaxValue)) { foreach (object o in book.GetEvents()) { stream.Add(new EventMessage { Body = @o }); } stream.CommitChanges(Guid.NewGuid()); book.ResetEvents(); } } public Book Get(Guid id) { using (var commits = this.store.OpenStream(id, 0, int.MaxValue)) { var eventsToReply = commits.CommittedEvents; return new Book(id, eventsToReply); } } } 

Teams

 public class BookNameChanged { public readonly Guid id; public readonly string title; public BookNameChanged(Guid id, string bookName) { this.id = id; this.title = bookName; } } public class BookSold { public readonly Guid id; public readonly int count; public BookSold(Guid id, int count) { this.id = id; this.count = count; } } 
+1
source share
1 answer

Good job for the first trip. Depending on how you connected, the fields, the fact that they are hare readonly and the lack of a parameterless open constructor are likely to cause problems with most serialization mechanisms - i.e. Will make them automatic properties.

While I usually prefer to protect invariants by holding back everything that you have, it is important to balance this with the fact that the event, once it happened, is completely baked - so POCO with writable properties is not as crazy as you I think.

Another thing I would do is get rid of event identifiers.

(And go to the DDD-CQRS mailing list - in a recent discussion on the concept of bold events, that is, repetition of material that can be gleaned from previous events [on the basis that you know that the event handler needs to respond to the event], which I agree is a bad idea).

I have to publish my AggregateBase - there are subtleties that you have, but many things that I would change. Knock me in a week if I don’t do it before ...

+1
source

All Articles