Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ const config: UserConfig<DefaultTheme.Config> = {
{ text: 'Full Text Searching', link: '/documents/full-text' },
{ text: 'Noda Time Support', link: '/documents/noda-time' },
{ text: 'Partial updates/patching', link: '/documents/partial-updates-patching' },
{ text: 'PLv8 Support', link: '/documents/plv8' },
{ text: 'AspNetCore Support', link: '/documents/aspnetcore' },
]
},
Expand Down
3 changes: 2 additions & 1 deletion docs/configuration/ioc.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

::: tip
The Marten team recommends using the `IServiceCollection.AddMarten()` extension method
for IoC integration out of the box.
for IoC integration out of the box and honestly, the full `IHost` integration. At this point Marten
depends on the `IHostedService` abstraction in .NET for start up actions and the async daemon.
:::

The Marten team has striven to make the library perfectly usable without the usage of an IoC container, but you may still want to
Expand Down
3 changes: 2 additions & 1 deletion docs/configuration/prebuilding.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ public static class Program

services.AddMarten(opts =>
{
opts.Events.AppendMode = EventAppendMode.Quick;
opts.GeneratedCodeMode = TypeLoadMode.Dynamic;
opts.AutoCreateSchemaObjects = AutoCreate.All;
opts.DatabaseSchemaName = "cli";
Expand Down Expand Up @@ -209,7 +210,7 @@ public static class Program
}
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CommandLineRunner/Program.cs#L28-L103' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_configuring_pre_build_types' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/CommandLineRunner/Program.cs#L29-L105' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_configuring_pre_build_types' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Okay, after all that, there should be a new command line option called `codegen` for your project. Assuming
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration/storeoptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ but you do need to tell Marten about any non-default length limit like so:
var store = DocumentStore.For(_ =>
{
// If you have overridden NAMEDATALEN in your
// PostgreSQL database to 100
// Postgresql database to 100
_.NameDataLength = 100;
});
```
Expand Down
14 changes: 13 additions & 1 deletion docs/documents/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
# Marten as Document DB

Marten's original focus was on enabling Postgresql as a document database for .Net developers that would allow developers to work very efficiently compared to the typical RDBMS + ORM approach while delivering solid performance. In Marten's case, persistent .Net _documents_ are just serialized to JSON and persisted to Postgresql using its unique JSONB capabilities. The advantage to developers of this approach is that there is much less configuration work necessary to map their persistent classes to a database structure. Developers are also far more able to evolve their application's model as there is so much less friction in changing the persistence layer with Marten compared to the RDBMS + ORM combination.
Marten's original focus was on enabling Postgresql as a document database for .Net developers. In Marten's case, this means
that instead of an ORM like EF Core where you have to map .NET types to flat relational database tables, Marten just utilizes
JSON serialization to persist and load .NET objects ("documents"). In conjunction with PostgreSQL's JSONB data type and its ability
to efficiently support rich querying and even indexing through JSON documents, Marten's approach has turned out to be highly
effective to implement persistence in many .NET applications.

When a document database is a good fit for a system (mostly when you have relatively self-contained entities and don't need to
model complex relationships between document types), Marten can make teams much more productive over ORM or purely relational
database usage by:

* Eliminating explicit ORM mapping
* Being able to accept changes as entities evolve without having to worry much about database migrations
* Utilizing built in database initialization and migrations at runtime so you can "just work"

Here's an introduction to Marten Db as a document database from .Net Conf 2018:

Expand Down
2 changes: 1 addition & 1 deletion docs/documents/querying/linq/projections.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public async Task can_do_simple_select_many_against_simple_array()

var names = query.Query<Product>().SelectMany(x => x.Tags).ToList();
names
.Count().ShouldBe(9);
.Count.ShouldBe(9);
}
}
```
Expand Down
81 changes: 78 additions & 3 deletions docs/events/metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,20 @@ where you append new events. At this point you can override:
Do note that if you want to potentially overwrite the timestamp of events _and_ you want to use the "QuickAppend" option
for faster appending, you'll need this configuration:

snippet: sample_setting_quick_with_server_timestamps
<!-- snippet: sample_setting_quick_with_server_timestamps -->
<a id='snippet-sample_setting_quick_with_server_timestamps'></a>
```cs
var builder = Host.CreateApplicationBuilder();
builder.Services.AddMarten(opts =>
{
opts.Connection(builder.Configuration.GetConnectionString("marten"));

// This is important!
opts.Events.AppendMode = EventAppendMode.QuickWithServerTimestamps;
});
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Examples/MetadataExamples.cs#L79-L90' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_setting_quick_with_server_timestamps' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The setting above is important because the `QuickAppend` normally takes the timestamp from the
database server time at the point of inserting database rows. The `QuickWithServerTimestamps` option changes Marten's
Expand All @@ -162,12 +175,74 @@ by default, or explicitly overridden data on `IEvent` wrappers.
Now, on to event appending. The first way is
to pull out the `IEvent` wrapper and directly setting metadata like this:

snippet: sample_overriding_event_metadata_by_position
<!-- snippet: sample_overriding_event_metadata_by_position -->
<a id='snippet-sample_overriding_event_metadata_by_position'></a>
```cs
public static async Task override_metadata(IDocumentSession session)
{
var started = new QuestStarted { Name = "Find the Orb" };

var joined = new MembersJoined
{
Day = 2, Location = "Faldor's Farm", Members = new string[] { "Garion", "Polgara", "Belgarath" }
};

var slayed1 = new MonsterSlayed { Name = "Troll" };
var slayed2 = new MonsterSlayed { Name = "Dragon" };

var joined2 = new MembersJoined { Day = 5, Location = "Sendaria", Members = new string[] { "Silk", "Barak" } };

var action = session.Events
.StartStream<QuestParty>(started, joined, slayed1, slayed2, joined2);

// I'm grabbing the IEvent wrapper for the first event in the action
var wrapper = action.Events[0];
wrapper.Timestamp = DateTimeOffset.UtcNow.Subtract(1.Hours());
wrapper.SetHeader("category", "important");
wrapper.Id = Guid.NewGuid(); // Just showing that you *can* override this value
wrapper.CausationId = wrapper.CorrelationId = Activity.Current?.Id;

await session.SaveChangesAsync();
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Examples/MetadataExamples.cs#L15-L44' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_overriding_event_metadata_by_position' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The second option is to directly append the `IEvent` wrappers where you've already
set metadata like this:

snippet: sample_override_by_appending_the_event_wrapper
<!-- snippet: sample_override_by_appending_the_event_wrapper -->
<a id='snippet-sample_override_by_appending_the_event_wrapper'></a>
```cs
public static async Task override_metadata2(IDocumentSession session)
{
var started = new QuestStarted { Name = "Find the Orb" };

var joined = new MembersJoined
{
Day = 2, Location = "Faldor's Farm", Members = new string[] { "Garion", "Polgara", "Belgarath" }
};

var slayed1 = new MonsterSlayed { Name = "Troll" };
var slayed2 = new MonsterSlayed { Name = "Dragon" };

var joined2 = new MembersJoined { Day = 5, Location = "Sendaria", Members = new string[] { "Silk", "Barak" } };

// The result of this is an IEvent wrapper around the
// started data with an overridden timestamp
// and a value for the "color" header
var wrapper = started.AsEvent()
.AtTimestamp(DateTimeOffset.UtcNow.Subtract(1.Hours()))
.WithHeader("color", "blue");

session.Events
.StartStream<QuestParty>(wrapper, joined, slayed1, slayed2, joined2);

await session.SaveChangesAsync();
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Examples/MetadataExamples.cs#L46-L75' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_override_by_appending_the_event_wrapper' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

::: tip
You can also create event wrappers by calling either:
Expand Down
24 changes: 23 additions & 1 deletion docs/events/storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,29 @@ two different `Created` types above. While you _could_ manually alias all of the
yourself to disambiguate, it's too easy to forget to do that. Instead, you can just switch to different
naming schemes like this:

snippet: sample_event_naming_style
<!-- snippet: sample_event_naming_style -->
<a id='snippet-sample_event_naming_style'></a>
```cs
var builder = Host.CreateApplicationBuilder();
builder.Services.AddMarten(opts =>
{
opts.Connection(builder.Configuration.GetConnectionString("marten"));

// This is the default behavior, but just showing you that
// this is an option
opts.Events.EventNamingStyle = EventNamingStyle.ClassicTypeName;

// This mode is "the classic style Marten has always used, except smart enough
// to disambiguate inner classes that have the same type name"
opts.Events.EventNamingStyle = EventNamingStyle.SmarterTypeName;

// Forget all the pretty naming aliases, just use the .NET full type name for
// the event type name
opts.Events.EventNamingStyle = EventNamingStyle.FullTypeName;
});
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/EventSourcingTests/Examples/NamingStyles.cs#L13-L34' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_event_naming_style' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Note that you will have to switch out of the "classic" naming mode to disambiguate between event types
with the same class name in different namespaces.
Expand Down
Loading