# Syntax Deep Dive and Procedure Calls This guide focuses on the two query syntaxes and advanced stored procedure invocation patterns. ## Two Query Syntax Styles DynamORM supports: - Dynamic table syntax: concise runtime calls via `dynamic`. - Fluent builder syntax: explicit SQL composition via interfaces and lambda parser. ## Dynamic Table Syntax Entry point: ```csharp dynamic users = db.Table("users"); ``` Typical reads: ```csharp var count = users.Count(columns: "id"); var first = users.First(columns: "id,first,last"); var one = users.Single(id: 19); var list = (users.Query(columns: "id,first", order: "id:desc") as IEnumerable).ToList(); ``` Dynamic filters with `DynamicColumn`: ```csharp users.Count(where: new DynamicColumn("id").Greater(100)); users.Count(where: new DynamicColumn("last").In("Hendricks", "Goodwin", "Freeman")); ``` Modifications: ```csharp users.Insert(code: "201", first: "Juri", last: "Gagarin"); users.Update(values: new { first = "Yuri" }, where: new { code = "201" }); users.Delete(code: "201"); ``` Coverage references: - `DynamORM.Tests/Select/DynamicAccessTests.cs` - `DynamORM.Tests/Modify/DynamicModificationTests.cs` ## Fluent Builder Syntax Entry points: ```csharp var q1 = db.From("users", "u"); var q2 = db.From("u"); ``` Composable select: ```csharp using (var query = db.From("u") .Where(x => x.u.id > 10) .Select(x => x.u.id, x => x.u.first) .OrderBy(x => x.u.id.Desc())) { var rows = query.Execute().ToList(); } ``` Parser forms supported by tests: - `From(x => x.dbo.Users)` - `From(x => x.dbo.Users.As(x.u))` - `From(x => "dbo.Users AS u")` - `From(x => x(subQuery).As("u"))` - `Join(x => x.Left().Accounts.As(x.a).On(x.a.userId == x.u.id))` Coverage references: - `DynamORM.Tests/Select/ParserTests.cs` - `DynamORM.Tests/Select/LegacyParserTests.cs` ## Choosing Between Syntaxes Use dynamic table syntax when: - You want short CRUD calls quickly. - Table/column selection is runtime-driven. Use fluent builder syntax when: - You want explicit SQL structure and deterministic command text. - You need complex joins/subqueries/parser features. - You prefer typed projections (`Execute()`, `ScalarAs()`). ## Stored Procedure Deep Dive `db.Procedures` provides dynamic invocation of stored procedures. ## Basic Calls ```csharp var r0 = db.Procedures.sp_Exp_Scalar(); var r1 = db.Procedures.sp_Exp_Scalar(); ``` ## Namespaced Procedure Names `TryGetMember` composes member segments before invocation: ```csharp var r = db.Procedures.dbo.reporting.sp_MonthlySales(); ``` Final procedure name becomes `dbo.reporting.sp_MonthlySales`. ## Direction Prefixes Argument name prefixes drive parameter direction: - `out_` => `ParameterDirection.Output` - `ret_` => `ParameterDirection.ReturnValue` - `both_` => `ParameterDirection.InputOutput` Example: ```csharp dynamic res = db.Procedures.sp_Test_Scalar_In_Out( inp: Guid.NewGuid(), out_outp: Guid.Empty, ret_Return: 0); ``` Returned object exposes values without prefixes. ## Advanced Parameter Shape You can pass: - plain values - `DynamicColumn` with schema and direction metadata - `DynamicSchemaColumn` - `DynamicExpando` / `ExpandoObject` Example with explicit output schema: ```csharp var res = db.Procedures.sp_Exp_SomeInputAndOutput( Name: "G4g4r1n", out_Result: new DynamicSchemaColumn { Name = "Result", Size = 256 }, ret_Return: 0); ``` ## Generic Result Shapes From `DynamicProcedureInvoker` behavior: - `T == IDataReader`: returns cached reader (`CachedReader()`). - `T == DataTable`: materializes via `ToDataTable()`. - `T == IEnumerable`: dynamic row enumeration. - `T == IEnumerable`: scalar conversion per row. - `T == IEnumerable`: mapping with mapper cache. - `T == class`: mapped single/object payload. ## Return and Output Aggregation When output/return params are present, DynamORM aggregates: - main result - each output parameter - return value into a dynamic object or mapped result type (if a mapping type is provided).