Add typed join specification builder syntax

This commit is contained in:
root
2026-02-26 18:42:35 +01:00
parent f28549c775
commit 23a0336b7e
5 changed files with 175 additions and 2 deletions

View File

@@ -43,6 +43,12 @@ namespace DynamORM.Builders
/// <returns>Builder instance.</returns>
IDynamicTypedSelectQueryBuilder<T> Join<TRight>(Expression<Func<T, TRight, bool>> on, string alias = null, DynamicJoinType joinType = DynamicJoinType.Inner);
/// <summary>Add typed join using join-spec builder syntax (<c>As()</c>, join kind and <c>On()</c>).</summary>
/// <typeparam name="TRight">Joined mapped entity type.</typeparam>
/// <param name="specification">Join specification builder callback.</param>
/// <returns>Builder instance.</returns>
IDynamicTypedSelectQueryBuilder<T> Join<TRight>(Func<TypedJoinBuilder<T, TRight>, TypedJoinBuilder<T, TRight>> specification);
/// <summary>Add INNER JOIN using typed ON predicate.</summary>
IDynamicTypedSelectQueryBuilder<T> InnerJoin<TRight>(Expression<Func<T, TRight, bool>> on, string alias = null);

View File

@@ -104,6 +104,20 @@ namespace DynamORM.Builders.Implementation
return this;
}
public IDynamicTypedSelectQueryBuilder<T> Join<TRight>(Func<TypedJoinBuilder<T, TRight>, TypedJoinBuilder<T, TRight>> specification)
{
if (specification == null)
throw new ArgumentNullException("specification");
TypedJoinBuilder<T, TRight> spec = specification(new TypedJoinBuilder<T, TRight>());
if (spec == null)
throw new ArgumentException("Join specification cannot resolve to null.", "specification");
if (spec.OnPredicate == null)
throw new ArgumentException("Join specification must define ON predicate.", "specification");
return Join(spec.OnPredicate, spec.Alias, spec.JoinType);
}
public IDynamicTypedSelectQueryBuilder<T> InnerJoin<TRight>(Expression<Func<T, TRight, bool>> on, string alias = null)
{
return Join(on, alias, DynamicJoinType.Inner);

View File

@@ -0,0 +1,76 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*/
using System;
using System.Linq.Expressions;
namespace DynamORM.Builders
{
/// <summary>Typed join specification builder used by typed fluent select queries.</summary>
/// <typeparam name="TLeft">Left side mapped type.</typeparam>
/// <typeparam name="TRight">Right side mapped type.</typeparam>
public class TypedJoinBuilder<TLeft, TRight>
{
internal TypedJoinBuilder()
{
JoinType = DynamicJoinType.Inner;
}
/// <summary>Gets join alias.</summary>
public string Alias { get; private set; }
/// <summary>Gets join type.</summary>
public DynamicJoinType JoinType { get; private set; }
/// <summary>Gets ON predicate.</summary>
public Expression<Func<TLeft, TRight, bool>> OnPredicate { get; private set; }
/// <summary>Sets join alias.</summary>
public TypedJoinBuilder<TLeft, TRight> As(string alias)
{
Alias = alias;
return this;
}
/// <summary>Sets INNER JOIN.</summary>
public TypedJoinBuilder<TLeft, TRight> Inner()
{
JoinType = DynamicJoinType.Inner;
return this;
}
/// <summary>Sets LEFT JOIN.</summary>
public TypedJoinBuilder<TLeft, TRight> Left()
{
JoinType = DynamicJoinType.Left;
return this;
}
/// <summary>Sets RIGHT JOIN.</summary>
public TypedJoinBuilder<TLeft, TRight> Right()
{
JoinType = DynamicJoinType.Right;
return this;
}
/// <summary>Sets FULL JOIN.</summary>
public TypedJoinBuilder<TLeft, TRight> Full()
{
JoinType = DynamicJoinType.Full;
return this;
}
/// <summary>Sets ON predicate.</summary>
public TypedJoinBuilder<TLeft, TRight> On(Expression<Func<TLeft, TRight, bool>> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
OnPredicate = predicate;
return this;
}
}
}