Tree organized repository child specifics
When master repository has hierarchy structure, than detail objects can be filtered by two methods to choose detail repository data: filter data linked with selected tree node only (direct links), and linked to subtree from selected node and below by hierarchy. XData has functional to choose one of this methods in runtime. To provide this ability mapping of master objects must describe external links marked as direct links. Than master repository flag ShowSubtree can be used as a switch between this two methods.
Let's explain that on example...
Mapping master tree organized data object...
private static Expression<CustomMapping<Catalog>> _unused = (
() => XDataMapping.CustomMapping<Catalog>()
.DataTable("R", "T_CATALOG")
.Map(x => new Catalog{
CatalogId = x.Field<long>("R", string.Empty, z => z.Key()),
Code = x.Field<string>("R", string.Empty),
Name = x.Field<string>("R", string.Empty),
ParentId = x.Field<long?>("R", string.Empty) },
// Direct link
x => x.ExternalLink<Document>(x => x.CatalogId, x => x.DirectLink()),
// Subquery link
x => x.ExternalLink<Document>(x => x.CatalogId,
z => z.Filter(y => new FilterName("FilterByRoot"))))
.SetBaseTable("R").SetFlags(DataStructureFlag.Tree)
);
Master data object SQL...
SELECT R.catalog_id AS R_catalog_id,
R.code AS R_code,
R.name AS R_name,
R.parent_id AS R_parent_id
FROM T_CATALOG R
Mapping detail data object...
private static Expression<CustomMapping<Document>> _unused = (
() => XDataMapping.CustomMapping<Document>()
.DataTable("D", "T_DOC")
.DataTable("DC", "T_DOC_CATALOG", x => x.Link("D", "doc_id"),
x => x.SubqueryFilter("catalog_id", "UT")
.SetOperation(FilterOperation.In))
.Subquery<CatalogTree>("UT", x => x.CatalogId, DataGrouping.None)
.Map(x => new Document{
DocId = x.Field<long>("D", string.Empty, z => z.Key()),
DocDate = x.Field<DateTime>("D", string.Empty),
CatalogId = x.Field<long>("DC", string.Empty) })
.SetBaseTable("D")
);
...
private static Expression<CustomMapping<CatalogTree>> _unused = (
() => XDataMapping.CustomMapping<CatalogTree>()
.With("CAT", XDataMapping.GetStructure("R")
.DataTable("T_CATALOG", "R",
x => x.ConstFilter("FilterByRoot", "parent_id",
FilterConstantType.Const, null,
FilterNullable.NullsCompared))
.Select(x => new {
CatalogId = x.Field<long>("R", string.Empty, z => z.Key()),
ParentId = x.Field<long?>("R", string.Empty),
}), x => x.Properties(z => z.CatalogId, z => z.ParentId),
x => x.WithRecursive("S", XDataMapping.GetStructure("S")
.DataTable("T_CATALOG", "S")
.Select(y => new {
CatalogId = y.Field<long>("S", string.Empty, z => z.Key()),
ParentId = y.Field<long?>("S", string.Empty)
}),
z => z.SubqueryLink(y => y.ParentId, y => y.CatalogId)))
.ReadOnlyProperty(x => x.CatalogId,
x => x.Field<long>("CAT", string.Empty, z => z.Key()))
.ReadOnlyProperty(x => x.ParentId,
x => x.Field<long?>("CAT", string.Empty))
.Map().SetFlags(DataStructureFlag.ReadOnly)
);
Link and using data objects with ShowSubtree off...
dataScope.GetReposytory<Catalog>()
.Do(x => x.Instance.GetChild<Document>())
.ToArray();
Detail data object SQL...
with recursive T (catalog_id, code, name, parent_id)
as ((SELECT R.catalog_id AS R_catalog_id,
R.parent_id AS R_parent_id
FROM T_CATALOG R
WHERE R.catalog_id = @FilterByRoot)
UNION ALL (SELECT S.catalog_id AS S_catalog_id,
S.parent_id AS S_parent_id
FROM T_CATALOG S, T T
WHERE S.parent_id = (T.catalog_id)))
SELECT D.doc_date AS D_doc_date /* DocDate */,
D.doc_id AS D_doc_id /* DocId */,
DC.catalog_id AS DC_catalog_id /* CatalogId */
FROM T_DOC D
JOIN T_DOC_CATALOGUE DC ON DC.doc_id = D.doc_id
WHERE DC.catalog_id in (SELECT T.catalog_id AS T_catalog_id FROM T T)
and DC.catalog_id = @FilterByCatalogId
Direct link is filled and detail data object data is restricted by single catalogue_id from master data object.
Link and using data objects with ShowSubtree on...
dataScope.GetReposytory<Catalog>()
.Do(x => x.Instance.GetChild<Document>(),
x => x.Instance.ShowSubtree = true)
.ToArray();
Detail data object SQL...
with recursive T (catalog_id, code, name, parent_id)
as ((SELECT R.catalog_id AS R_catalog_id,
R.parent_id AS R_parent_id
FROM T_CATALOG R
WHERE R.catalog_id = @FilterByRoot)
UNION ALL (SELECT S.catalog_id AS S_catalog_id,
S.parent_id AS S_parent_id
FROM T_CATALOG S, T T
WHERE S.parent_id = (T.catalog_id)))
SELECT D.doc_date AS D_doc_date /* DocDate */,
D.doc_id AS D_doc_id /* DocId */,
DC.catalog_id AS DC_catalog_id /* CatalogId */
FROM T_DOC D
JOIN T_DOC_CATALOGUE DC ON DC.doc_id = D.doc_id
WHERE DC.catalog_id in (SELECT T.catalog_id AS T_catalog_id FROM T T)
Direct link not filled and data not restricted by single catalogue_id from master data object. Resulted detail data will match master data object current record subtree.