Clues about AIProfile map to document store

🔒 You must be logged in as an Administrator or Editor to listen to this audio.

That is a fantastic question. When looking at standard relational database code (like Entity Framework), you usually see obvious attributes like [Table("Profiles")] or [Key].

However, in Orchard Core, YesSql operates differently. YesSql is a document database (even though it runs on top of SQL), which means it stores entire C# objects as serialized JSON documents. Because of this, the AIProfile.cs file itself doesn't need heavy database mapping attributes.

Here is exactly how we know it is designed for YesSql, based on the code provided—and an explanation of the "missing" code that actually handles the mapping.

1. The Clues Inside AIProfile.cs

While the mapping isn't explicit in this file, there are three massive clues that this class is designed for a JSON-based document store like YesSql:

  • The JSON Attributes: YesSql converts objects to JSON to store them in the database's Document table. The presence of [JsonIgnore], [JsonInclude], and [JsonPropertyName("DeploymentId")] proves this object relies heavily on JSON serialization rules to save and load its state correctly.
  • The JsonObject Settings Property: It contains an arbitrary JsonObject Settings { get; init; }. In a strict relational SQL table, storing arbitrary JSON is cumbersome. In YesSql, because the whole AIProfile is saved as a single JSON document, adding arbitrary nested JSON settings is native and seamless.
  • Inheriting CatalogItem: In the Clone() method, you can see ItemId = ItemId. Orchard Core models stored in YesSql typically use a unique string identifier (often Id or ItemId) rather than a standard auto-incrementing integer for external references. CatalogItem is the base class providing this identity.

2. The Code That Actually Maps It to YesSql (Index Providers)

In YesSql, classes are just Plain Old C# Objects (POCOs). The actual code that "maps" AIProfile to the database isn't in AIProfile.cs. Instead, it lives in two other places in the Orchard Core module: The Manager/Store and The Index Provider.

A. Saving the Document (The Store)

Somewhere in the CrestApps module (likely a file named AIProfileStore.cs), there is code injecting Orchard Core's ISession. YesSql simply takes the object and saves it as a document like this:

// Example of how YesSql saves the AIProfile
public async Task SaveAsync(AIProfile profile)
{
    // ISession is YesSql's main interface
    _session.Save(profile); 
}

B. Querying the Document (The Index Provider)

Because YesSql stores the whole AIProfile as a big JSON string, you can't easily run a SQL query like WHERE OrchestratorName = 'Agent'.

To solve this, YesSql uses Index Providers. If you were to look through the CrestApps source code, you would find a class that looks something like this. This is the actual code that maps properties from the document to SQL columns for fast querying:

// This is the YesSql mapping code (likely found elsewhere in the CrestApps repository)
public class AIProfileIndex : MapIndex
{
    public string Name { get; set; }
    public string OrchestratorName { get; set; }
    public AIProfileType Type { get; set; }
}

public class AIProfileIndexProvider : IndexProvider<AIProfile>
{
    public override void Describe(DescribeContext<AIProfile> context)
    {
        // THIS is the mapping! 
        // It tells YesSql: "When you save an AIProfile document, pull out these 
        // specific properties and put them in a dedicated SQL table for fast searching."
        context.For<AIProfileIndex>()
            .Map(profile =>
            {
                return new AIProfileIndex
                {
                    Name = profile.Name,
                    OrchestratorName = profile.OrchestratorName,
                    Type = profile.Type
                };
            });
    }
}

Summary

You don't see database mapping in AIProfile.cs because YesSql is designed to be unobtrusive. It lets your models remain pure data containers (with JSON instructions). The actual database mapping is separated into IndexProvider classes so that your core models aren't cluttered with database logic.