DataSource API: ProvideOut(...)
DataSources always provide data on an Out
Stream. The ProvideOut()
method makes it very easy to do.
How to use ProvideOut
In general, you need
- a method like
GetList()
which returns anIEnumerable<IEntity>
- attach that stream to the
Out
- usually on a stream calledDefault
Here's a simple example of the constructor of the Tutorial Basic DataSource, which provides the default stream:
/// <summary>
/// Constructor to tell the system what out-streams we have
/// </summary>
public DateTimeDataSourceBasic()
{
ProvideOut(GetList); // "Default" out; when accessed, will deliver GetList
}
/// <summary>
/// Get-List method, which will load/build the items once requested
/// Note that the setup is lazy-loading so this code will only execute when used
/// </summary>
private IEnumerable<IEntity> GetList()
{
var date = DateTime.Now;
var values = new Dictionary<string, object>
{
{DateFieldName, date},
{"Weekday", date.DayOfWeek},
{"DayOfWeek", (int) date.DayOfWeek}
};
// Construct the IEntity and return as ImmutableArray
var entity = DataFactory.Create(values);
return new [] {entity};
}
This example ensures that the .Out["Default"]
as well as the .List
(which is a shorthand for .Out["Default"].List
) are mounted, ready to deliver.
Overloads
ProvideOut(listfunction)
- default version, which provides the "Default" streamProvideOut(listfunction, name)
- alternative for named streams when your DataSource has more streams.ProvideOut(listfunction, name: name, options: optionsfunction)
- optimized for conversions when using CustomDataSource.
Providing multiple streams
In case you want to offer multiple streams (like one containing products, the other categories), the common pattern is:
public SomeConstructor()
{
ProvideOut(GetProducts);
ProvideOut(GetCategories, "Categories");
// ...
}
Providing Data with Relationships
In some cases you want the created Entities to have relationships to each other. Examples could be:
- Blog posts with relationships to their tags
- Tree structures such as folders
- etc.
For this you should first understand how relationships are created. Every created entity is immutable. This means that it can't be modified once created. Now this poses a special challenge, because some of the referenced entities may not exist when the referencing entity (aka the parent) is created.
So internally there is a lookup concept, which basically works like this:
- A Relationship Manager knows about all the entities and how they can be referenced
- An entity which needs other entities will get this manager injected
- A field which references other entities keeps a list of references - either the IDs or special strings like
file-of:/some/path
- When the field is accessed, internally it will ask the ReferenceManager to find the entities
For creating relationships you must do two things:
- Ensure that each new entity provides the keys it should be found on. If you are only using IDs, you don't have to do anything, but if you need magic strings, you must provide them.
- Tell the relationship fields (eg:
MyChildren
orParent
) what IDs / keys to use.
Here's a simple example from the tutorial:
using System.Collections.Generic;
public class TreeBasic : Custom.DataSource.DataSource16
{
public TreeBasic(MyServices services) : base(services, "My.Magic")
{
ProvideOut(() => {
return new List<object> {
// Root has ID 1 and points to 2 children
CreateNode(1, "Root Node", new [] { 101, 102 }),
// This is a subnode, with 2 more children
CreateNode(101, "Sub Item 101", new [] { 1011, 1012 }),
CreateNode(102, "Sub Item 102"),
CreateNode(1011, "Sub Item 1011"),
CreateNode(1012, "Sub Item 1012"),
};
});
}
private object CreateNode(int id, string title, int[] relationships = null) {
return new {
Id = id,
Title = title,
// To reference another item in the same list,
// create an anonymous object with "Relationships" as an Enumerable, Array or List
SubItems = new { Relationships = relationships }
};
}
}
This example skips step one, because it only uses IDs.
As you can see, the property SubItems
creates a special object which contains the references to the children of a parent.
💡 For more examples, check out the Relationships Tutorial
Performance Notes
It's important to know that ProvideOut
simply prepares the Out
for use, but will not call the inner function unless this stream is requested. This makes DataSources very performant, as no code is run which isn't needed.
Read also
History
- Introduced in EAV 4.x, 2sxc 09.13
- Changed from
Provide
toProvideOut
in v15 (breaking change)