Read only dynamic query building
XData have a feature allow the programmer to build read-only data query in dynamic LINQ like style:
var query = XDataMapping.GetStructure("D")
.DataTable("T_DOC", "D",
x => x.DictFilter("T_DOC_TYPE", "doc_type_id", "code", "INVOICE"))
.DataTable("T_DOC_NUMBER", "N", x => x.Link("D", "doc_id"))
.DataTable("T_DOC_SCAN", "SC", x => x.Link("D", "doc_id"))
.DataTable("T_DOC_DELIVERY", "DD", x => x.Link("D", "doc_id"))
.DataTable("T_DOC_SOURCE", "SR", x => x.Link("D", "doc_id"))
.Subquery("A", typeof(DocSpecAmounts), "Amount",
DataGrouping.Sum, x => x.SubqueryLink("DocId"))
.InnerView("H", XDataMapping.GetStructure("H")
.DataTable("T_DOC_HISTORY", "H")
.Select(x => new {
DocId = x.Field<int?>("H", string.Empty,
z => z.Key(), z => z.Group(DataGrouping.None)),
HistoryDate = x.Field<DateTime?>("H", string.Empty,
z => z.Group(DataGrouping.Max))
}), x => x.SubqueryLink(z => z.DocId)
.SetOperation(FilterOperation.OuterJoin))
.Column("DocId", x => x.Field<int?>("D", "doc_id", z => z.Key()))
.Select(x => new {
Number = x.Field<string>("N", "numb"),
Date = x.Field<DateTime>("D", "doc_date"),
Amount = x.Expr<decimal?>("doc_amount", DataExpressionType.SubQuery,
"A", DbType.Decimal, z => z.Size(17, 5)), //SUBQUERY
LastChange = x.Ref<object>("H", "HistoryDate"), //INNER VIEW
Scan = x.Field<byte[]>("SC", string.Empty), //BLOB
DeliveryType = x.Field<DeliveryTypeEnum>("DD", string.Empty), //ENUM
Source = x.Field<string>("SR", string.Empty) //XML
}).AsQuery(dataScope);
foreach (var x in query)
Console.WriteLine(
"Number:{0}, Date:{1}, Amount:{2}, Scan:{3}, LastChange:{4}, DeliveryType:{5}, Source:{6}",
x.Number, x.Date, x.Amount, Encoding.UTF8.GetString(x.Scan), x.LastChange, x.DeliveryType,
x.Source);
Static class XDataMapping has method GetStructure to obtain IQueryStructure<T> interface having various methods to describe very complicated query structure dynamically. Rules of building queries dynamically is similar as dynamic mapping but query more lightweight, safe and can be extended in runtime.
Method GetStructure has overloaded version to get structure of existing repository to extend it with adding data sources as data tables, subqueries and inner views, applying filters including filters by subqueries. Query mapping logic can be declared by Select method returning IQueryDescription<T> interface. No matter statically or dynamically is mapped repository we use as source structure, it can be extended.
To access query data get IQueriable implementation IDataQuery<T> from IQueryDescription<T> use AsQuery method. With dynamic query You can query and map data to any object including real-time typed object as showed in example.
Dynamic mapping has no method to add filters in runtime. To add new filter to QueryStructure used method AddFilters.