Skip to content

Commit

Permalink
docs: improvements for beginners to reduce confusion
Browse files Browse the repository at this point in the history
  • Loading branch information
ascott18 committed Mar 20, 2024
1 parent aee7964 commit a9f1e7c
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 66 deletions.
9 changes: 8 additions & 1 deletion docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,15 @@ export default defineConfig({
items: [
autoTitle("/modeling/model-types/entities"),
autoTitle("/modeling/model-types/external-types"),
autoTitle("/modeling/model-types/dtos"),
autoTitle("/modeling/model-types/services"),
{
text: "Advanced",
collapsed: true,
items: [
autoTitle("/modeling/model-types/dtos"),
autoTitle("/modeling/model-types/standalone-entities"),
]
},
],
},
{
Expand Down
61 changes: 0 additions & 61 deletions docs/modeling/model-types/entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,64 +39,3 @@ The method by which you can control what data the users of your application can

Behaviors in Coalesce are to mutating data as data sources are to reading data. Defining a behaviors class for a model allows complete control over the way that Coalesce will create, update, and delete your application's data in response to requests made through its generated API. Read [Behaviors](/modeling/model-components/behaviors.md) to learn more.


## Standalone (non-EF) Entities

In Coalesce, Standalone Entities are entity types that are not based on Entity Framework. These types are discovered by Coalesce by annotating them with `[Coalesce, StandaloneEntity]`.

For these types, you must define at least one custom [Data Source](/modeling/model-components/data-sources.md), and optionally a [Behaviors](/modeling/model-components/behaviors.md) class as well. If no behaviors are defined, the type is implicitly read-only, equivalent to turning off create/edit/delete via the [Security Attributes](/modeling/model-components/attributes/security-attribute.md).

To define data sources and behaviors for Standalone Entities, it is recommended you inherit from `StandardDataSource<T>` and `StandardBehaviors<T>`, respectively. For example:

``` c#
[Coalesce, StandaloneEntity]
public class StandaloneExample
{
public int Id { get; set; }

[Search(SearchMethod = SearchAttribute.SearchMethods.Contains), ListText]
public string Name { get; set; } = "";

[DefaultOrderBy]
public DateTimeOffset Date { get; set; }

private static int nextId = 0;
private static ConcurrentDictionary<int, StandaloneExample> backingStore = new ConcurrentDictionary<int, StandaloneExample>();

public class DefaultSource : StandardDataSource<StandaloneExample>
{
public DefaultSource(CrudContext context) : base(context) { }

public override Task<IQueryable<StandaloneExample>> GetQueryAsync(IDataSourceParameters parameters)
=> Task.FromResult(backingStore.Values.AsQueryable());
}

public class Behaviors : StandardBehaviors<StandaloneExample>
{
public Behaviors(CrudContext context) : base(context) { }

public override Task ExecuteDeleteAsync(StandaloneExample item)
{
backingStore.TryRemove(item.Id, out _);
return Task.CompletedTask;
}

public override Task ExecuteSaveAsync(SaveKind kind, StandaloneExample? oldItem, StandaloneExample item)
{
if (kind == SaveKind.Create)
{
item.Id = Interlocked.Increment(ref nextId);
backingStore.TryAdd(item.Id, item);
}
else
{
backingStore.TryRemove(item.Id, out _);
backingStore.TryAdd(item.Id, item);
}
return Task.CompletedTask;
}
}
}
```

The above example is admittedly contrived, as it is unlikely that you would be using an in-memory collection as a data persistence mechanism. A more likely real-world scenario would be to inject an interface to some other data store. Data Source and Behavior classes are instantiated using your application's service provider, so any registered service can be injected.
61 changes: 61 additions & 0 deletions docs/modeling/model-types/standalone-entities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

# Standalone Entities

In Coalesce, Standalone Entities are types that behave like [entity types](./entities.md) (they can support the full suite generated CRUD endpoints), but are not based on Entity Framework. These types are discovered by Coalesce by annotating them with `[Coalesce, StandaloneEntity]`.

For these types, you must define at least one custom [Data Source](/modeling/model-components/data-sources.md), and optionally a [Behaviors](/modeling/model-components/behaviors.md) class as well. If no behaviors are defined, the type is implicitly read-only, equivalent to turning off create/edit/delete via the [Security Attributes](/modeling/model-components/attributes/security-attribute.md).

To define data sources and behaviors for Standalone Entities, it is recommended you inherit from `StandardDataSource<T>` and `StandardBehaviors<T>`, respectively. For example:

``` c#
[Coalesce, StandaloneEntity]
public class StandaloneExample
{
public int Id { get; set; }

[Search(SearchMethod = SearchAttribute.SearchMethods.Contains), ListText]
public string Name { get; set; } = "";

[DefaultOrderBy]
public DateTimeOffset Date { get; set; }

private static int nextId = 0;
private static ConcurrentDictionary<int, StandaloneExample> backingStore = new ConcurrentDictionary<int, StandaloneExample>();

public class DefaultSource : StandardDataSource<StandaloneExample>
{
public DefaultSource(CrudContext context) : base(context) { }

public override Task<IQueryable<StandaloneExample>> GetQueryAsync(IDataSourceParameters parameters)
=> Task.FromResult(backingStore.Values.AsQueryable());
}

public class Behaviors : StandardBehaviors<StandaloneExample>
{
public Behaviors(CrudContext context) : base(context) { }

public override Task ExecuteDeleteAsync(StandaloneExample item)
{
backingStore.TryRemove(item.Id, out _);
return Task.CompletedTask;
}

public override Task ExecuteSaveAsync(SaveKind kind, StandaloneExample? oldItem, StandaloneExample item)
{
if (kind == SaveKind.Create)
{
item.Id = Interlocked.Increment(ref nextId);
backingStore.TryAdd(item.Id, item);
}
else
{
backingStore.TryRemove(item.Id, out _);
backingStore.TryAdd(item.Id, item);
}
return Task.CompletedTask;
}
}
}
```

The above example is admittedly contrived, as it is unlikely that you would be using an in-memory collection as a data persistence mechanism. A more likely real-world scenario would be to inject an interface to some other data store. Data Source and Behavior classes are instantiated using your application's service provider, so any registered service can be injected.
2 changes: 1 addition & 1 deletion docs/stacks/vue/coalesce-vue-vuetify/components/c-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- MARKER:summary -->

A general-purpose input component for most [Values](/stacks/vue/layers/metadata.md). c-input does not have much functionality of its own - instead, it delegates to the right kind of component based on the type of value to which it is bound. This includes both other [Coalesce Vuetify Components](/stacks/vue/coalesce-vue-vuetify/overview.md) as well as direct usages of some [Vuetify](https://vuetifyjs.com/) components.
A general-purpose input component for most [Values](/stacks/vue/layers/metadata.md). c-input delegates to other components based on the type of value it is bound to. This includes both other [Coalesce Vuetify Components](/stacks/vue/coalesce-vue-vuetify/overview.md) as well as direct usages of some [Vuetify](https://vuetifyjs.com/) components.

<!-- MARKER:summary-end -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

A dropdown component that allows for selecting values fetched from the generated ``/list`` API endpoints.

Used both for selecting values for foreign key and navigation properties, and for selecting arbitrary objects or primary keys independent of a parent or owning object.
Used for selecting values for foreign key and navigation properties, or for selecting arbitrary objects or primary keys without a parent or owning object.

<!-- MARKER:summary-end -->

Expand Down
17 changes: 15 additions & 2 deletions docs/stacks/vue/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@

# Getting Started

## Environment Setup
Before you begin, ensure that you have all the requisite tools installed
- Recent version of the [.NET SDK](https://dotnet.microsoft.com/en-us/download). If you have Visual Studio, you already have this.
- A recent version of [Node.js](https://nodejs.org/) (an LTS version is recommended).
- A compatible IDE.
- Recommended:
- Visual Studio for backend (C#) development
- VS Code for frontend (Vue, TypeScript) development (with [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) and [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin))
- Also consider:
- VS Code for full stack development.
- JetBrains Rider


## Creating a Project

The quickest and easiest way to create a new Coalesce Vue application is to use the ``dotnet new`` template. In your favorite shell:
Expand All @@ -26,9 +39,9 @@ The Vue template is based on [Vite](https://vitejs.dev/). You are strongly encou

The structure of the Web project follows the conventions of both ASP.NET Core and Vite. The Vue-specific folders are as follows:

- ``/src`` - Files that should be compiled into your application. CSS/SCSS, TypeScript, Vue SFCs, and so on.
- ``/src`` - Files that should be compiled into your frontend application. CSS/SCSS, TypeScript, Vue SFCs, and so on.
- ``/public`` - Static assets that should be served as files. Includes index.html, the root document of the application.
- ``/wwwroot`` - Target for compiled output.
- ``/wwwroot`` - Target for compiled output. This directory is excluded from git.

During development, no special tooling is required to build your frontend code. Coalesce's ``UseViteDevelopmentServer`` in ASP.NET Core will take care of that automatically when the application starts. Just make sure NPM packages have been installed (`npm ci`).

Expand Down

0 comments on commit a9f1e7c

Please sign in to comment.