►
Description
Want the productivity gains of a NoSQL approach with ACID compliance and the ability to fall back to SQL when needed? Interested in event sourcing but don't want all different infrastructure for that? Come check out Marten and Postgresql!
A
A
C
C
So
today
we're
gonna
be
talking
about
project
called
Martin's.
Then
they
spelled
with
an
E
because
what
it
really
refers
to-
and
here
I
didn't
think
to
pull
a
picture
of
it,
but
everybody
we
got
to
see
how
cute
these
guys
are.
First,
so
Martin
is
actually
not
named
after
a
person
is
named
after
these
cute
little
boogers
I'm
about
to
show
on
the
screen
and
just
a
second
yeah.
These
guys
see
how
cute
that
guy
is
so
that
that's
what
Martin's
actually
named
after
not
a
person,
so
Martin
is
a
client
library.
C
It's
a
dotnet.
You
distribute
as
a
dead
nougat
that
allows
you
to
treat
the
Postgres
QL
database
as
both
a
document
database
in
an
event
store
inside
of
a
dotnet
application.
Now
well,
next,
we'll
go
into
why
in
the
world
did
we
think
this
is
a
good
idea,
and
why
might
you
be
interested
in
trying
to
get
some
of
this?
It's
a
little
bit
of
a
funky
idea?
Well,
let's
get
into
it
so
first
off
at
the
end
of
this,
if
you're
still
not
scared
away,
we've
got
quite
a
bit
of
community
around
this.
C
We're
up
to
almost
80
80
contributor,
so
far--
got
a
lot
of
documentation
and
samples
up
on
our
web
site.
We
always
find
something
that
that
that's
missing,
but
we've
tried.
The
code
itself
is
up
on
github
it's
under
an
MIT
license,
so
you
can
pull
it
down
copy
it
and
make
fun
of
it.
Take
whatever
you
want
out
of
it
and
then
finally,
I'm
a
huge
fan
of
git
er
for
having
an
embedded
chat
room
for
attached
real
closely
to
your
github
repository
and
that's
the
best
place
to
go.
Ask
questions
about
Martin,
alright!
C
So
just
a
little
bit
of
a
history
so
about
the
2014-2015
time
frame
at
a
former
at
a
former
employer,
my
colleague,
Corey
Taylor
and
I
were
kind
of
talking
and
he
had
the
idea
that
hey
we
used
raven
DB
very
heavily
and
we
loved
the
development
experience,
but
we're
having
some
trouble
with
it
in
in
production
scenarios,
and
it
was
getting
the
point
where
we
knew
we
had
to
replace
it
one
way
or
another.
But
raven
DB
s--
usage
is
very
different
than
what
you
would
get
from
many
other
persistence
frameworks
or
databases.
C
So
we
kicked
around
the
idea.
Corey
actually
had
the
idea
of
give
him
credit
what
if
we
could
take
PostgreSQL
hey,
it's
got
some
pretty
cool
json
support.
What
if
we
could
turn
that
and
make
it
act,
just
like
Ravin
DB
and
we
can
swap
it
in
and
out
so
from
that
conversation
and
a
whole
lot
of
time
later,
Martin
itself
was
born,
that's
kind
of
an
add
on
that.
That's
actually
turned
in
and
maybe
the
most
popular
feature
Martin.
C
We
also
looked
at
adding
event
sourcing
support
in
the
library,
with
an
eye
towards
replacing
very,
very
old
versions
in
event
store
in
our
shop.
So
we
got
to
roll
out.
It
finally
went
1.0
in
September
of
2016.
It
had
actually
been
in
production
in
a
very
large
production,
app
quite
a
few
months
before
that
2.0
came
out
last
summer
with
a
lot
of
improvements
in
the
internals,
a
lot
of
work
to
reduce
memory
allocations
and
generally
make
everything
as
efficient
as
we
can
possibly
make
it.
C
There's
a
3.0,
that's
in
progress,
but
it's
not
progressing
super
fast
and
I'm
not
going
to
demo
any
new
features
here
today.
But
it's
coming
so
let's
talk
about
some
of
the
very
different
ways
you
could
do
application
persistence,
kind
of
look
at
where
Martin
might
fit.
In
so
most
of
my
career,
we've
use
just
old-fashioned
relational
databases.
Maybe
we
put
other
stuff
on
top
of
it.
Maybe
we
put
out
o
R
M.
C
Some
of
those
tools
I,
don't
necessarily
like
it
for
a
lot
of
transactional
applications,
but
sequels
awfully
hard
to
beat
for
reporting
and
there's
a
whole
lot
of
investment
that
we
probably
all
have
porting
tools
and
learning
sequel
and
all
the
third
party
stuff
that
already
supports
database
binding.
So
there's
plenty
of
good
reasons
to
keep
relational
databases
around.
What
will
mostly
be
talking
about
in
this
talk
is
using
a
document
database
huge
advantages
for
developer
productivity.
C
In
my
opinion,
other
cases
you
might
use
event
sourcing,
where
I
don't
store
the
exact
state
of
the
current
system.
My
system
of
record
I'm
a
beast
events
as
they
happen.
It's
like
an
invoice
II
system,
an
invoice
is
created,
an
invoice
was
approved
so
on
and
so
forth
and
from
that
raw
event,
data
that
may
be
valuable
in
itself
off
to
the
side.
We
calculate
and
create
a
read
side,
current
state
of
the
world
addressing
the
relational
models,
various
kinds
of
ORM,
so
maybe
we
use
any
framework.
Maybe
we
use
something
lighter
like
dapper.
C
The
cool
thing
about
Martin
here
is
that
it
allows
you
to
mix
and
match
any
of
these
tools.
Martin
itself
supports
the
document,
databases
of
insourcing,
but
at
the
same
time,
because
it's
sitting
on
top
of
a
relational
database,
you
can
happily
use
anything
that
Postgres
offers.
You
could
happily
use
an
ORM
with
it
and
we
have
specific
integration
with
dapper,
not
that
that
really
means
much.
We
just
expose
the
connections,
so
you
can
use
it
dapper
with
it
to
your
heart's
content,
so
you're
not
stuck
with
just
Martin
you're
able
to
choose
whatever
persistence.
C
Ok,
so
if
you're
not
familiar
with
any
kind
of
no
sequel
system,
or
specifically
a
document
database,
why
you
would
care
about
it
what
it
does
for
you,
if
you
think
about
using
an
ORM
today,
that's
probably
the
most
common
pattern,
you're
spending
a
little
bit
and
maybe
a
lot
of
time
doing.
Mapping
where
does
an
object
model
property
land
in
a
database
field.
Hopefully
the
database
and
object
model
looks
like
a
lot
of
times
they
really
shouldn't
and
it
makes
it
a
little
harder
for
you
to
try
to
do
those
mappings.
C
Maybe
you
have
object
hierarchies
that
don't
fit
the
database.
Well,
maybe
you
have
deep
complex
objects
where
you
have
to
start
to
span
a
lot
of
different
tables
to
make
it
work
in
a
relational
model.
Document
database
is
really
nice,
especially
when
you
get
into
hierarchical
model,
you're,
not
mapping
your
structure,
what
we're
doing,
and
especially
with
Martin
you're,
just
sterilizing
your
objects
to
JSON
and
stuffing
it
into
a
single
column
in
the
database.
C
All
right,
your
schema
is
your
objects,
so
some
of
the
great
things
that
does
for
you
that
the
advantages
that
gives
us
as
developers
it's
a
whole
lot
less
mechanical
work
to
make
things
happen,
not
spending
any
time
with
JSON
I'm,
not
creating
two
completely
separate
models,
a
storage
model
and
a
model
for
my
business
logic.
I
just
worry
about
what
the
document
structures
like
in
c-sharp
make
sure
that
the
inevitable
you
bitte
quiz
Newton
soft
JSON,
can
serialize
it
and
I'm
good
to
go.
C
C
You
pay
a
penalty
anytime,
there's
extra
cost
for
changing
code,
so
taking
the
example
of
adding
a
field
and
going
all
the
way
from
adding
it
to
your
object,
and
you
feel
to
the
database
table
having
a
database
migration
so
on
and
so
forth.
A
document
database
at
development
time
is
will
see
with
Martin.
You
wouldn't
have
to
do
a
thing,
add
a
new
property
to
your
document
and
you
are
off
and
running.
There's
no
extra
work
to
touch
your
database.
C
We
get
much
less
friction
for
making
additional
changes
to
to
our
objects.
It
allows
us
to
play
with
design
ideas
because
we
can
adapt
to
the
database
very
quickly.
There
are
some
database
migrations.
We
are
still
running
in
Postgres
sequel.
We
do
still
have
to
manage
the
database
schema,
but
it's
just
that
the
database
schema
is
going
to
change
much
much
less
often,
this
last
bullet
point.
This
is
actually
a
big
deal,
so
the
trend
I've
seen
the
last
several
years,
software
development
and
the
way
we
approach
automated
testing.
C
It
shifted
much
more
towards
trying
to
incorporate
much
more
integration,
testing
at
least
intermediate
level
testing,
and
it
means
going
all
the
way
through
the
database
as
opposed
to
trying
so
so
so
hard
to
isolate
things,
and
they
can
code
more
complex
just
to
be
able
to
get
unit
tests
without
the
database.
So
if
you
take
that
idea
that
integration
testing
is
a
good
thing,
we
always
have
to
make
sure
that
we
have
a
either
clean
or
a
known
state
in
our
database
before
we
test
through
it.
C
The
document
database
actually
makes
us
a
lot
easier,
especially
if
something
like
Barton
or
what
we
did
previously
with
Raven.
You
can
effectively
do
a
complete
wipe
of
the
database
with
a
single
command
in
Martin
before
any
kind
of
automated
tests.
It
makes
it
very
easy
to
effectively
provision
a
brand-new
database
schema
per
test
right
if
you've
done
any
work
with
relational
databases
inside
of
automated
tests.
That
can
be
a
lot
more
complicated,
relational
integrity,
making
sure
you
delete
things
tables
in
the
right
way.
It's
just
a
lot
of
extra
work.
C
So
WIPO
script,
sequel
and
let
me
get
this
one
out
of
the
way
fast,
every
time,
I've.
Given
this
talk,
somebody
asks
the
logical
question
is:
why
did
you
not
use
sequel
server?
This
is
a
dinette
tool.
Most
done
in
shops
want
to
use
sequel
server,
they're
more
familiar
with
it
and
we'll
be
honest.
We
know
that
Martin
would
probably
be
have
much
more
adoption
if
we'd
been
able
to
use
single
server.
So
our
belief
is
that
martin
is
using
a
lot
of
features
that
are
very
specific
to
Postgres
sequel
around
its
JSON
support.
C
We
think
long
term
that
not
the
current
version
of
sequel
server,
but
the
next
version
of
Postgres
version
11
and
hopefully,
whatever
the
next
version
of
the
sequel,
server,
that
sequel
server
will
reach
enough
parity
and
both
of
them
will
support
a
sequel,
slash,
JSON
spec.
That
kind
of
standardized
is
how
you
address
the
JSON
data
inside
the
database
with
JSON
path,
but
that
would
make
it
a
lot
more
possible
a
lot
easier
for
us
to
finally
make
martin
database
agnostic,
but
for
right
now,
Postgres
pretty
awesome.
It's
super
easy
to
install.
C
C
Very
hard,
and
very
fast,
but
specifically
for
Martin.
It
has
a
lot
of
really
unusual
JSON
features.
The
the
JSON
itself
is
stored
in
a
special
column,
type
called
JSON
B.
That
is
a
binary
representation
of
the
JSON
document,
which
enables
Postgres
to
reach
into
the
json
documents
much
more
easily
and
much
more
efficiently.
Okay,
part
of
my
original
original
goals,
building
building
martin
was
we
also
needed
to
get
on
to
something
with
that
kind
of
usability,
but
we
need
to
have
grown
up
DevOps
tools.
C
C
Simple
one
at
that,
so
let's
say
we
have
a
very
simple
c-sharp
class
like
this
order
class.
That's
on
the
screen
order.
Class
itself
may
have
one
or
many
many
order
details,
and
you
see
that
I'm
using
a
custom
enumeration
for
the
priority
as
quickly
as
possible.
We
want
to
get
this
spun
up
where
we
can
persist
and
load
these
these
little
order
classes
with
Martin
Lee.
So.
C
First
thing:
I
want
to
do
need
to
create
a
document
store
for
Martin
and
in
this
case
we're
not
customizing
anything
we're,
not
configuring
anything.
We
can
go
with
all
the
default
default
options,
so
the
only
thing
I
need
to
do
is
just
say:
I
want
a
document
store
for
this
connection
string
and
right
now.
This
is
pointing
to
an
instance
of
Postgres
that
I
don't
check
this.
C
As
I
said
very
much
earlier,
we
have
just
a
little
handy
helper
that
will
allow
you
to
completely
clean
off
your
database
schema
and
start
over
and
that's
what
I
did
did
here
with
the
code.
That's
highlighted,
looking
in
the
right
of
of
our
IDE
now,
there's
no
tables
at
all
in
our
public
schema
just
that
curiosity
for
anybody
who's
wondering
if
you've
never
seen
this
before
I'm
using
Jeb
brains,
writer
for
all
the
demos
today,
just
giving
Jeff
brains
a
big
shout
out,
they
have
been
very
generous.
C
They
give
I,
have
an
OSS
license
from
them
and
Martin's
pretty
well
supported
and
built
now,
at
least
from
my
side
with
Jeb
range
writer.
So
we
have
no
database,
but
we
have
an
order.
Class
we'd
really
like
to
get
it
persisted,
so
we
have
a
store
so
that
represents
that
is
going
to
be
a
singleton
object
within
your
system.
I,
don't
there's
not
a
direct
analog
inside
of
any
framework,
but
if
you're
familiar
with
in
hibernate,
that's
I'd,
say
that's
roughly
now,
I
guess
to
the
ice
session
factory
from.
B
C
Hibernate,
so
to
get
to
Martin's
version
of
the
dbcontext,
we
need
to
get
at
an
ID
documents
session
and
that's
what's
happening
in
this
method
right
here.
So
the
document
session
represents
a
unit
of
work
to
Martin,
so
it
allows
you
to
establish
transactional
boundaries
and
it
exposes
everything
you
would
possibly
need
to
query
a
Martin
datastore
in
this
particular
case.
We're
gonna
create
an
order,
object
and
we'll
notice
here,
I'll
come
back
to
this.
C
At
no
point,
do
we
actually
set
a
value
for
the
ID
here,
as
you
can
probably
guess,
the
ID
property
that's
going
to
end
up
being
the
primary
key
in
the
database,
but
getting
back
to
it
so
we're
going
to
create
a
session
we're
going
to
tell
the
session
that
hey
I
want
to
store
this
order.
Document
save
changes
here.
C
In
one
command
to
the
database
below
that
will
go
fetch
a
completely
separate
session,
just
to
make
sure
we're
not
getting
any
kind
of
cache
copy
from
this
one
and
we'll
try
to
load
the
order
back
from
the
ID
that's
been
magically
assigned.
It
just
proved
that
it's
all
there
so
I'm
gonna
run
the
test
here.
C
Okay,
you
succeeded
down
here
so
a
couple
things
Martin
just
just
by
convention.
If
it
sees
a
property
called
ID,
it
assumes
that
that's
the
identity
for
your
object.
There
are
some
ways
to
override
that,
but
going
with
all
the
defaults,
so
just
working
with
it
idiomatically.
The
way
it
wants
to
it
knows
that
ID
is,
is
our
primary
key
and
because
it's
a
grid,
if
you
try
to
store
it
with
an
empty
grid
with
we'll
just
quietly,
make
a
new
grid
for
you
and
assign
it
to
the
document
itself
before
it
persists
it.
C
For
those
we
are
a
little
more
her
a
little
more
familiar
with
it.
It
is
a
sequential
grid
so
that
it
saves
and
loads
quite
a
bit
more
efficiently
to
the
database,
and
right
after
that,
we've
been
able
to
load
that
that
order
by
its
ID
we've
done
no
mapping.
We've
done
no
configuration
just
to
prove
that
stuff
actually
exists.
Let's
take
a
peek
in
the
database,
so
on
the
fly
we
created
an
order
object
or
an
order
table
that
stores
it
there's
not
a
lot
of
stuff
going
on.
C
C
So
not
super
exciting,
but
that's
a
good
thing
we
didn't
have
to
have
any
drama.
We
didn't
have
to
do
a
lot
of
configuration.
We
added
the
Martin
Martin
nougat
reference
and
we
created
a
document
store
for
the
connection
string
because
I'm
using
all
the
defaults.
This
is
running
in
a
development
mode,
meaning
that
it
will
create
any
necessary
tables.
It
needs
to
on
the
fly
if
they
don't
are
existent
in
the
database.
C
C
Let's
say
the
order
has
some
kind
of
address.
Maybe
it's
a
billing
address.
Who
knows
what
it
is
so
just
another
little
type
here
and
you'll
notice.
There
is
no
ID
on
this.
We
don't
have
to
the
address
when
it's
persisted
as
a
property
of
the
order.
It's
going
to
be
persisted
directly
in
the
order.
I
don't
have
to
create
other
tables.
I,
don't
have
to
think
about
anything
else
to
come
back
into
this
test.
Let's
go
ahead
and
add.
C
C
C
Most
of
you,
if
you
have
no
background
with
no
sequel
or
only
a
little
background,
with
no
sequel,
you're
kind
of
wondering.
Why
am
I
making
a
big
deal
here
in
this
slide
that
Martin
and
really
just
Postgres,
underneath
it
is
completely
acid
compliant?
This
is
something
you've
always
had
in
relational
databases.
This
is
something
you
always
expect
to
have.
You
can't
believe
people
try
to
do
without
this,
but
a
lot
of
the
no
sequel,
databases,
and
probably
especially
the
early,
no
sequel
databases
did
not
have
were
not
acid
compliance.
C
Most
of
them
had
some
kind
of
some
kind
of
eventual
consistency
where
rights
happened
immediately,
but
you
were
not
ain't
necessarily
able
to
immediately
read
or
query
over
this.
The
state
there'd
be
a
little
bit
of
gap
when
the
reads
were
not
in
sync
with
the
state
of
the
database.
This
is
a
huge
deal
for
us.
As
we
moved
from
my
previous
shop,
we
moved
from
Raven
DB
to
Martin.
It
was
something
we
knew
we
wanted
so
just
to
prove
this.
We.
C
C
We're
gonna
we're
gonna,
throw
a
thousand
of
these
into
the
database
as
best
as
we
can
so
we've
got
here
and
then,
as
fast
as
we
can
we're
gonna
come
back
and
we're
gonna
query
that
we
can
pick
out
how
many
of
these
are
green
I'll,
just
to
prove
that
we
can
immediately
query
against
the
data
we
just
inserted.
Just
run
these
real
quick.
C
And
we
look
here
super
fast
here
we
get
an
all
new,
all
new
database
session.
So
if
you
look
at
the
bottom
left
spinning
ball,
we
got
the
green
checkmark.
It
just
worked.
So
there's
nothing.
You
have
to
do
here
that
this
is
actually
pretty
rare
for
a
no
sequel
approach.
This
ability
to
immediately
query
against
the
data
that
was
just
inserted
without
any
kind
of
eventual
consistency
catching
up
on
the
read
state.
That's
a
huge
deal.
C
B
C
C
Different
properties,
different
values,
different
behavior,
when
you
pull
them
down
when
we
work
against
the
persistence,
sometimes
we
want
to
see
all
the
orders
together.
I
want
to
see
all
the
domestic
and
alright,
all
the
domestic
and
international
orders
for
a
certain
part
and
I
want
to
treat
it
just
in
order,
but
other
times
I
want
to
Lotus
the
Civic
type
of
part.
I
want
to
order
order,
load,
an
international
order
or
domestic
order.
I
want
to
use
linked
queries
against
either
the
subtype
or
the
parent
type.
Okay.
C
This
is
something
Martin
supports
out
of
the
box,
not
nearly
as
much
effort
that
you
have
a
third
object
with
a
no
RM
I.
Don't
have
to
think
about.
Do
I
have
a
separate
table
per
type.
Do
I,
try
to
put
them
all
in
the
same
type.
Do
I
have,
like
extension
properties
in
the
very
sparse
table.
How
do
I
map
that
forget
all
that
stuff,
Martin's
gonna
take
care
of
most
of
the
force?
C
One
thing
we
do
have
to
do,
though,
is
we
just
have
to
tell
Martin
for
the
order
class
I
want
you
to
also
include
the
Civic
subclasses
for
domestic
order
and
international
order
now
coming
down
into
usage
just
showing
here
I
can
create
a
domestic
order.
I
put
all
the
properties
in
I
want
I
created
international
order,
and
we
just
added
something
on
the
fly.
C
Because
I
think
we
were
making
fun
of
of
hottie
from
JetBrains
earlier
today
on
Twitter,
for
something
let's
say
it's
going
to
Spain
and
I
can
store.
One
I
can
store
two
save
them
both
and
I.
Come
back
and
I
can
load
them
as
an
order
or
I
can
love
them
specifically,
as
the
subclass
I
can
query
any
possibly
mix-match
here.
C
Looking
at
the
bottom
left
just
to
make
sure
the
test
passes
and
there
it
does
just
the
cutesy
little
thing
this
last
one
here
so
I
want
to
query
a
domestic
order
where
the
customer
idea
is
somebody
and
all
I'm
doing
is
Martin
has
a
little
little
helper.
That
will
allow
you
to
preview
what
the
sequel
command
is
for
a
link.
Query
so
I'm
using
that
just
to
grab
the
sequel
to
be
generated.
Bottom
right,
just
see
we're
looking
over
this
ugly
table.
Name
and
I
am
limiting
the
query.
C
C
Alright,
so
that's
the
basics,
saving
and
loading
documents
just
to
JSON.
If
this
is
all
there
was
to
it,
you
could
probably
code
this
up
by
yourself
honestly,
pretty
fast,
except
for
the
LINQ
query,
part
bust
everybody's
bubble.
The
LINQ
query
part
is
super
work,
intensive,
really
monotonous,
and
if
you
liked
the
link
provider
and
whatever
database
tool,
you
use
give
some
positive
thoughts
and
think
you
used
to
ever
wrote
that
because
it's
miserably
time-consuming,
but
so
some
of
the
things
we've
done
to
try
to
make
martin
fast.
C
A
C
That's
what
we're
doing
here,
there's
a
little
more
power
here
to
say:
do
I
want
this
to
be
unique.
Do
I
want
it
to
be
use
all
the
the
special
features
and
types
of
of
indexes
and
Postgres,
but
it's
probably
what
you
want
to
do
so,
when
I'm
issuing
a
query
now
down
below
where
I
want
to
say,
I
want
to
look
for
where
the
color
property
is
is
green,
Postgres
is
able
to
apply
that
index,
just
like
you
would
with
relational
database.
C
When
you
set
a
query
on
a
column
that
you
frequently
search
over
all
the
same
problems,
database
indexes
that
always
exist,
you
always
have
to
wonder-
is
this
this
creating
more
overhead
on
inserts?
Then
it
gives
us
in
value
on
speeding
up
reads:
same
same
rules
apply
the
bigger
one
and
the
speeds,
some
of
the
other
things
we
do
out
of
the
box.
Our
default
JSON
sterilizer
is
Newton
soft
JSON.
It's
it's
the
obvious
choice
as
the
default,
because
it's
the
most
battle-tested
it
works
for
everything.
C
Some
weird
things
still
leaked
through,
especially
especially
some
oddball
things
like
f-sharp
types
or
we've
had
a
couple.
People
wanting
to
query
against
note
of
time
objects
that
kind
of
give
us
some
trouble
to
JSON
serialization,
but
it's
rock-solid,
but
if
you
want
to
we've,
been
able
to
swap
out
and
use
Jill
as
a
faster
sterilizer
or
some
of
the
newer
Chauncy
laser
alternatives,
so
you
can
opt
in
to
maybe
and
get
some
better
performance
by
going
to
a
different,
json
sterilizer
and
still
use
it
with
everything
that
martin
does
actually
had.
C
It
had
a
little
bit
of
conversation
with
with
a
trainer
in
in
Houston
that
I
or
I
had
sat
in
on
his
vb6
classes
20
years
ago,
and
he
had
this
phrase
and
stuck
with
me
ever
since
Network
round
trips
are
evil
fastest
way
to
make
your
your
enterprise
system
really
really
slow
is
to
be
really
chatty.
Making
a
lot
of
consecutive
calls
to
database
a
little
bit
of
information
when
developing
martin.
We
were
trying
to
be
very
cognizant
of
that.
C
We've
tried
to
minimize
the
number
of
batch
query
or
the
number
of
round
trips
the
database
as
possible
when
you're
committing
it's
a
database,
a
document
session.
It's
trying
to
send
the
commands
all
in
one
one
network,
roundtrip
same
thing
with
queries:
I
don't
have
an
example.
Example
in
this
talk,
but
you
can
set
up
multiple
queries
like
if
you
need
to
get
at
one
document
type
in
another
and
grab
them
all
at
one
time.
So
try
to
minimize
the
number
of
transcripts.
Excuse
me
the
feature
that
I'm
most
proud
of.
C
So
take
a
look
at
this
find
bicolor
class
I
have
highlighted
here
so
that
same
query,
we've
been
doing
where
I
want
to
just
find
all
the
targets
where
its
color
is
green
and
that's
what
we've
we're
expressing
here
by
this
fine
by
color
class.
It
looks
a
little
funky,
you're,
definitely
going
to
be
depended
upon
resharper
or
coderush,
or
something
like
that
to
generate
the
signatures
for
you
from
this
this
interface.
But
let
me
try
to
explain
why
this
thing
is
so
cool.
C
Let's
take
a
look
at
how
it's
used
so
instead
of
using
a
blink
query
directly
I'm
going
to
use
the
sessions,
query
query
there's
an
overload
that
it
will
allow
you
to
pass
in.
One
of
these
compiled
queries
so
I'll
create
that
object
pass
it
in
here,
and
it
basically
does
the
same
thing
as
if
this
is
the
equivalent
of.
C
So
this
is
actually
the
equivalent
of
that,
so
why
this
is
so
awesome,
even
though
it
looks
really
funky.
The
mechanics
of
doing
queries
by
link
are
super
duper
inefficient.
So
this
is
just
thinking
about
all
the
things
that
happen.
When
you
issue
a
late
query,
you're
creating
a
whole
bunch
of
little
objects.
It
may
not
feel
like
it,
but
you're
creating
a
lot
of
objects
in
that
little
expression
where
you
you
do
the
where
Clause.
C
So
when
you
pass
the
link
query
in
your
link
provider
has
to
take
all
these
little
objects,
and
this
is
probably
more
fun
if
you
could
see
all
the
goofy
hand
motions
I'm
doing,
but
it's
got
a
walk
down
this
tree,
and
this
really
excruciating
lilo
to
eat
low-level
detailed
model
of
what
are
all
the
expressions
there's
in
here
and
or
here
what
property
is?
It's
got
a
parse
all
through
all
that
stuff
figure
out.
C
What's
going
on
interpret
all
that
object
model,
then
to
a
bunch
of
strengthen
catenation,
come
up
with
a
sequel
command
and
then
figure
out
how
the
data
combined
is
up
going
to
an
object
model
and
so
on
and
so
forth.
It's
a
lot
of
mechanical
work
to
interpret
a
link
expression
and
do
something
useful.
The
compiled
query
feature
in
Martin.
C
C
C
And
finally,
and
especially,
if
you
come
from
the
MongoDB
world,
we
have
the
ability
in
the
way
of
something
we
call
the
patching
API
where,
instead
of
trying
to
download
the
whole
document,
putting
it
into
a
dotnet
object,
changing
it
and
sending
it
back,
you
could
just
say:
I
want
to
change
the
property
within
a
document
in
the
database
to
this
value.
It
actually
takes
a
lot
of
advantage
of
JavaScript
functionality,
a
JavaScript
function
running
inside
of
Postgres.
To
make
that
happen.
C
To
some
other
special
features-
and
this
will
be-
this
will
be
much
better
supporter
than
to
Martin
3.0.
Whatever
that
happens,
so
the
documents
are
stored
in
JSON
in
the
database.
In
some
cases,
Newton
soft
might
have
to
put
some
some
ugly
net
serialization
stuff
in
there
for
type
information.
But
most
of
the
time
that
JSON
is
pretty
clean,
it
may
be
perfectly
possible
to
just
take
the
raw
JSON
and
go
grab
it
because
Martin
will,
let's
just
get
the
JSON
string
and
immediately
toss
it
down
an
HV
response
for
really
efficient
HP
web
services.
C
You
know
some
of
you
are
saying,
oh,
but
you
know
you're,
never
supposed
to
put
your
your
object
model
across
the
wire,
which
is
true
and
awfully
a
lot
of
the
time
so
along
those
lines.
So,
rather
than
pulling
in
your
object
and
using
something
like
automap
or
to
translate
it
to
a
totally
different
view,
model
and
c
relies
that
down
your
hv
response.
What
you
can
do
instead
is
use
a
JavaScript
function
that
takes
the
raw
JSON
of
your
model
and
changes
it
into
the
representation
that
you
want
to
go
out
of.
C
This
for
for
martin
3.0.
We
want
to
go
a
little
bit
farther
today.
You
have
to
to
create
a
JSON
string
to
pull
this
off,
which
it's
still
some
object.
Allocations
in
martin
3.0
we're
looking
at
a
model
where
you
could
just
stream,
basically
just
stream
the
the
bytes,
the
raw
bytes
from
the
Postgres
world,
directly
into
the
HIV
response,
without
even
having
to
allocate
a
string
looking
for
just
the
absolute
fastest
possible
way
to
have
web
services
that
just
deliver
data
out
of
the
database.
But
that
is
yet
to
come.
C
C
Let
me
back
up
so
hopefully,
when
you
look
at
Martin's
event
sourcing,
it
looks
pretty
familiar
and
one
of
the
reasons
it
should
look
be
pretty
familiar
if
you've
used
any
other
event
sourcing
tool
in
the.net
world.
Is
we
all
pretty
well
started
by
reading
Greg
young
seminal
paper
on
event,
sourcing
and
kind
of
going
from
there,
so
in
the
case
of
Martin,
just
just
like
like
get
event
store
or
innov
in
store
or
several
other
tools,
we
have
really
two
concepts.
C
C
C
We
have
events
where
members
show
up
and
join
join
the
join
the
party,
maybe
at
other
times
Sam
and
Frodo,
take
the
boat
and
go
off
on
their
own
and
everybody
else
leaves
leave
the
party
they
get
to
certain
destinations.
Maybe
they
slay
monsters
whatever
it's
gonna
be.
So
if
it
sourcing,
we
don't
have
a
master
document
of.
What's
the
state
of
the
quest
party,
we're
tracking
all
these
events,
members
joined
arrived
at
a
location.
C
C
Somebody
filled
out
an
invoice,
then
maybe
you
added
an
item.
Finally
to
prove
the
invoice
is
paid
tracking
those
kinds
of
events.
So,
in
our
case,
let's
start
out
we're
gonna
create
a
new
quest
and
we're
gonna
record
just
a
couple
events
at
a
time
it
started
on.
Maybe
we
record
what
day
it
is,
but
we're
gonna
say
the
name
of
our
quest
started.
C
We're
gonna,
add
some
members,
so
these
guys
started
out
and
on
day
one
and
then
also
a
day.
Five,
this
guy
Tom
he
ran
off
so
I'm
gonna
create
the
same
kind
of
session
from
the
store
duck
his
store
document
session,
because
all
this
has
exposed
there.
Everything
is
off
property.
Called
events
show
some
of
the
things
it
does
and
that
was
more
complicated
than
I
was
expecting
it
to
be.
C
Okay,
nevermind,
no
scary,
one
of
the
things
I
can
do
is
I
can
say
all
right,
I'm
gonna
start
a
brand
new
stream
of
events
and
I'm
gonna
specify
what
the
stream
is
right
here.
I
can
let
Martin
do
this,
but
what
we're
going
to
specifically
say
it's
as
particular
quit
and
then
I'm
just
going
to
tag
on
these
events
to
it
save
my
changes.
Events
part
of
the
same
unit
of
work
you
can
mix
and
match
persisting.
C
Events
are
appending
events
to
a
stream
with
saving
documents
and
that
that
comes
into
play
in
a
minute.
When
we
talk
about
projections
coming
down
the
line,
let's
say
we
have.
We
pick
up
a
couple
new
team
members
on
say
day:
seven,
we
pick
up
these
extra
characters
and
we
can
append
them
to
the
to
the
same
stream
of
events.
So
we
could
be
tracking
multiple
quests.
We
could
be
tracking
the
Lord
of
the
Rings,
which
we
tracking
Wheel
of
Time
Bulgaria,
whatever,
whatever
epic
fantasy
book,
you
love
loved
as
a
kid,
but
keeping
straight.
C
What
party
is
doing?
What
at
what
time,
so
that
that's
tracking
the
raw
data
and
I
think
most
people
to
get
hung
up
on
event
sourcing,
or
at
least
my
initial
reaction
is
well
persisting.
The
events
that
sounds
pretty
easy.
You
know,
especially
in
our
case,
we
have
one
table
and
we're
persisting
an
ID,
maybe
a
timestamp,
maybe
maybe
an
order
and
JSON
XML,
some
kind
of
serialization
of
the
events,
that's
great.
How
do
we
work
with
that
data?
Because
sooner
or
later
we
need
to
see
what
is
the
current
state
of
the
system?
C
Some
kind
of
what
the
CPS
folks
will
talk
about
is
the
breed
side
model
of
view.
So
event
sourcing
may
be
directly
connected
to
your
event,
sourcing
tool.
Maybe
it's
an
add-on.
You
have
an
idea
of
projected
views
taking
the
raw
event,
event
data
and
putting
them
together
and
trying
to
come
up
with
what
is
the
state
of
the
system.
C
Let
me
just
look
at
another
guy
called
quest
part,
so
real
simplistically.
Let's
say
that
what
we
care
about
is
the
name
of
a
quest,
it's
stream'
identity
and
just
tracking
who's
part
of
who's.
Part
of
our
quest
party
right
now,
you
know
if
I
ask
you
right
now,
who's
in
the
party
and
that's
just
the
state
here,
but
we
derived
this
by
looking
at
the
raw
data
of
like
events
like
members
join
members.
Departed
quest
started
all
this
kind
of
thing.
C
So
at
some
point
we
want
to
calculate
from
the
events
we
want
to
calculate
and
build
up
the
state
of
this
thing
and
the
code
you
see
highlighted
it's
not
the
only
way
to
do
this
in
Martin,
but
for
very
simple
aggregate
projections.
One
way
to
do
this
is
just
have
an
apply
method
for
every
event
that
would
have
every
event
type
that
would
apply
what
you're
trying
to
project
out
now.
Timing,
wise,
it's
something!
I
takes
a
little
bit
unique
to
Martin,
Martin's
event,
sourcing,
but
I
think
everybody
should
get
around
to
supporting
it.
C
These
projections
can
be
find
and
with
roughly
with
three
different
time
frames.
I
can
either
do
it
live,
which
means,
if
I
get
into
a
case,
where
I
have
lots
and
lots
of
event
rights,
but
I
very,
very
rarely
do
I
ever
try
to
read
what
the
exact
state
of
the
world
is.
I
might
decide.
The
best
thing
to
do
is
I'm
just
gonna.
Do
the
aggregation
completely
on
the
fly
when
I
ask
for
it,
and
only
then
in
there
will
I
try
to
see
what
the
state
is.
C
C
So
if
I
know
what
the
my
stream
identity
is,
my
quest
party
ID
just
ask
it
on
the
fly:
go
load
up
all
the
events
run
it
through
the
aggregation
and
tell
me
what
you
get
out
the
end.
That's
order
to
see
up
here
so
we
should
see
our
members
should
be
Rand,
Matt,
Peron
Tom
left,
so
you
should
be
subtracted
Lorraine
and
LAN.
C
We
run
the
test
as
always
we're
look
at
the
results.
We
should
see
some
JSON
in
the
bottom
right,
please,
okay,
and
there
are
members
and
there's
also
the
name
of
the
quest.
So
that's
a
little
doing.
It
live
so
again.
The
recommendation
there
is.
Maybe
you
do
that
when
you
have
lots
of
Rights,
so
you
want
to
optimize.
How
fast
can
you
write
the
data
into
the
system?
So
you
don't
want
to
be
calculating
anything.
You
just
want
to
capture
as
fast.
C
You
can
and
just
occasionally
read
the
state
and
it's
not
that
big
a
deal
to
wait
a
little
bit
to
create
the
read
side.
Other
thing,
that's
maybe
a
little
bit
unique
to
Martin.
Well,
we
can
now
say
is:
let's
say
the
quest
party
I
want
that
updated
as
you
capture
the
events,
that's
what
we
call
an
inline
projection.
C
So,
with
quest
party
now
I'm
going
to
do
just
a
little
bit
of
extra
configuration
with
Martin
I'm
going
to
say,
I
want
the
quest
party
to
be
aggregated
inline,
just
meaning
that
when
we
capture
any
events
that
are
related
to
quest
party
I
want
that
quest
party
projection
value
updated
as
part
of
the
same
unit
of
work.
What
means
what
that
means
is
the
when
I
try
to
commit
my
unit
of
work?
C
C
C
Is
you
have
some
kind
of
background
process?
That's
reading
through
all
the
events
coming
through
and
it's
trying
to
keep
up
and
updating
the
projections
as
it
can,
so
you
commit
the
commit.
You
commit
the
events,
its
persistence
in
the
database.
The
background
process
is
listening
for
all
the
events
coming
in
and
a
little
bit
later
got
an
eventual
consistency
thing
going
on.
So
this
isn't
purely
this
is
the
only
place
where
Martin
isn't
purely
I
said
it's
going
to
get
around
updating
the
breed
side
model
for
you.
C
So,
with
the
price
of
the
eventual
consistency
and
a
potential
for
making
mistakes
by
showing
data
before
something's
process,
if
you
have,
if
you're
concerned
that
you're
doing
a
lot
of
aggregation
across
streams
or
aggregation
where
it's
very
likely
you're
going
to
get
session
contention
on
the
projected
values,
it's
just
pretty
easy
to
do.
Let's
say
that
in
our
quest
party
system,
we
want
to
have
a
a
separate
view
of
how
many
monsters
have
been
slain
at
any
one
time.
C
So
in
that
case,
every
event
across
every
possible
stream
that
involves
slaying
a
monster
would
have
to
fetch
that
that
one
system-wide
aggregate
document
change
it
and
commit.
So
you
would
have
a
tremendous
amount
of
collisions.
What
we
can
do
is
we
can
switch
to
an
asynchronous
model
for
our
projections,
for
just
that
kind
of
view.
C
Make
sure
I
have
an
example
of
that,
so
we
have
a
feature
and
in
Martin
we
call
the
async
demon.
That
is
a
little
bit
of
Linux
Linux
Envy
on
my
part,
calling
it
a
daemon
where
I
can
set
up
make
sure
we
do
this.
So
I
can
throw
a
bunch
of
events
in,
but
I
can
create
this
long-running
demon
sit
in
memory
heavily
utilizing,
TPL
dataflow
to
be
to
be
consistent.
C
There's
a
lot
more
complexity
in
here
than
it
sounds,
but
it's
constantly
pulling
the
database
to
see
if
there
are
new
events
that
it
cares
about
that
are
referenced
in
some
kind
of
projection
that
are
part
of
the
async
daemon
and
it's
trying
to
make
sure
that
it
hangs
around
and
applies
everything
in
the
exact
same
order.
So
it's
sitting
running
in
the
background
trying
to
update
these
aggregated
documents,
performance
wise.
C
I
should
say
didn't
get
into
this
enough,
but
to
projected
documents.
So
the
reason
why
I
think
it
actually
made
sense
to
add
an
event
sourcing
feature
right
onto
Martyn
the
projected
read
side
documents,
they're
just
our
documents,
so
you
can
query
them.
You
can
load
them
by
IDE.
You
can
query
them
with
any
part
of
the
link
provider.
You
can
do
anything
you
want.
We
think
that
the
easy
integration
instrument
system
read
side
projected
documents
with
the
raw
event
data
capture.
C
It
is
a
huge
feature
and
a
win
for
Martin
versus
other
solutions
where
you
may
have
to
piece
together.
You
know
a
raw
event
store
which
may
be
saving
its
data
to
a
completely
different
data
store
versus
some
kind
of
unrelated
projection
tool.
Putting
your
read
side
in
some
completely
other
way,
not
everybody's
gonna
agree
with
that,
but
many
of
our
users
on
on
martin
that
enjoy
the
event
sources
support.
A
Not
here,
that's
yeah
we're
right
on
time.
Jeremy
just
you
know,
I
figured
we
started
late,
it
sort
of
it
got
pushed
around.
So
you
know
it's.
It's
all
good
from
here,
Thank
You
Jeremy,
for
taking
a
time
to
talk
to
us
and
dotnet
Kampf.
There's
some
questions
out
on
the
twitch
channel
to
keep
on
on
par
with
the
schedule.
We're
gonna
I
ask
if
you
can
jump
over
there.
We
can
answer
this
question,
so
you
and
I
can
kind
of
TAC
team
them.