The simplest data source we can query is an in-memory .NET collection registered with ctx.MemorySource()
.
But how the collection is populated remains up to you. The example below shows registering collections from
multiple sources inc. in-line code, populated from a CSV file (utilizing ServiceStack's
CSV deserialization support) and populated from a 3rd Party API using
HTTP Utils:
//Declaration in code
var countries = new[] {
new Country { ... },
new Country { ... },
};
//From CSV File
List<Currency> currencies = File.ReadAllText("currencies.csv").FromCsv<List<Currency>>();
//From 3rd Party API
List<GithubRepo> repos = "https://api.github.com/orgs/ServiceStack/repos"
.GetJsonFromUrl(req => req.UserAgent="AutoQuery").FromJson<List<GithubRepo>>();
//AutoQuery Data Plugin
Plugins.Add(new AutoQueryDataFeature { MaxLimit = 100 }
.AddDataSource(ctx => ctx.MemorySource(countries))
.AddDataSource(ctx => ctx.MemorySource(currencies))
.AddDataSource(ctx => ctx.MemorySource(repos))
);
After data sources are registered, you can then create AutoQuery Data Services to query them:
[Route("/countries")]
public class QueryCountries : QueryData<Country> {}
[Route("/currencies")]
public class QueryCurrencies : QueryData<Currency> {}
[Route("/repos")]
public class QueryGithubRepos : QueryData<GithubRepo> {}
With just the empty Request DTO's above they're now queryable like any other AutoQuery Service, e.g:
- /countries?code=AU
- /currencies.json?code=AUD
- /repos.csv?watchers_count>=100&orderBy=-watchers_count,name&fields=name,homepage,language
Queryable PocoDataSource​
PocoDataSource is useful for quickly creating an In Memory Queryable Data Source as done in the TODOs MVC Jamstack Examples:
public class TodosServices : Service
{
public IAutoQueryData AutoQuery { get; set; }
static readonly PocoDataSource<Todo> Todos = PocoDataSource.Create(new Todo[]
{
new () { Id = 1, Text = "Learn" },
new () { Id = 2, Text = "Blazor", IsFinished = true },
new () { Id = 3, Text = "WASM!" },
}, nextId: x => x.Select(e => e.Id).Max());
public object Get(QueryTodos query)
{
var db = Todos.ToDataSource(query, Request);
return AutoQuery.Execute(query, AutoQuery.CreateQuery(query, Request, db), db);
}
public Todo Post(CreateTodo request)
{
var newTodo = new Todo { Id = Todos.NextId(), Text = request.Text };
Todos.Add(newTodo);
return newTodo;
}
public Todo Put(UpdateTodo request)
{
var todo = request.ConvertTo<Todo>();
Todos.TryUpdateById(todo, todo.Id);
return todo;
}
// Handles Deleting the Todo item
public void Delete(DeleteTodo request) => Todos.TryDeleteById(request.Id);
public void Delete(DeleteTodos request) => Todos.TryDeleteByIds(request.Ids);
}
Where it provides ThreadSafe CRUD operations to manage a collection of In Memory POCOs.
In Memory AutoQuery​
The QueryTodos
implementation utilizes an AutoQuery Memory Source with the full capabilities of AutoQuery's Implicit Conventions:
Where it can be used to iteratively prototype new data models under a productive dotnet watch workflow until it satisfies all your requirements where it could be easily converted to AutoQuery CRUD APIs and integrated with your Systems configured RDBMS - which would require even less code.
Cacheable Data Sources​
The examples above provides a nice demonstration of querying static memory collections. But Data Sources offers even more flexibility where you're also able to query and cache dynamic .NET collections that are customizable per-request.
The registration below shows an example of this where results are dynamically fetched from GitHub's API and persisted in the local in-memory cache for 5 minutes - throttling the number of requests made to the external 3rd Party API:
.AddDataSource(ctx => ctx.MemorySource(() =>
$"https://api.github.com/repos/ServiceStack/{ctx.Request.GetParam("repo")}/contributors"
.GetJsonFromUrl(req => req.UserAgent="AutoQuery").FromJson<List<GithubContributor>>(),
HostContext.LocalCache,
TimeSpan.FromMinutes(5)
));
We can now create an AutoQuery Data Service to query the above cached GithubContributor
Memory Source:
[Route("/contributors")]
public class QueryContributors : QueryData<GithubContributor>
{
public string Repo { get; set; }
}
Thanks to the Typed Request DTO we also get an end-to-end Typed API for free which we can use to query the contributors result-set returned from GitHub's API. As an example we can view the Top 20 Contributors for the ServiceStack Project with:
var top20Contributors = client.Get(new QueryContributors {
Repo = "ServiceStack",
OrderByDesc = "Contributions",
Take = 20
});
top20Contributors.PrintDump(); // Pretty print results to Console