Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 75d8970

Browse files
committed
Add more join overloads and more tests
1 parent 4c537ad commit 75d8970

File tree

4 files changed

+60
-11
lines changed

4 files changed

+60
-11
lines changed

src/ServiceStack.OrmLite/Expressions/SqlExpression.Join.cs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,32 @@ public abstract partial class SqlExpression<T> : ISqlExpression
1010
List<ModelDefinition> tableDefs = new List<ModelDefinition>();
1111

1212
public SqlExpression<T> Join<Source, Target>(Expression<Func<Source, Target, bool>> joinExpr = null)
13+
{
14+
return InternalJoin("INNER JOIN", joinExpr);
15+
}
16+
17+
public SqlExpression<T> LeftJoin<Source, Target>(Expression<Func<Source, Target, bool>> joinExpr = null)
18+
{
19+
return InternalJoin("LEFT JOIN", joinExpr);
20+
}
21+
22+
public SqlExpression<T> RightJoin<Source, Target>(Expression<Func<Source, Target, bool>> joinExpr = null)
23+
{
24+
return InternalJoin("RIGHT JOIN", joinExpr);
25+
}
26+
27+
public SqlExpression<T> FullJoin<Source, Target>(Expression<Func<Source, Target, bool>> joinExpr = null)
28+
{
29+
return InternalJoin("FULL JOIN", joinExpr);
30+
}
31+
32+
private SqlExpression<T> InternalJoin<Source, Target>(string joinType,
33+
Expression<Func<Source, Target, bool>> joinExpr)
1334
{
1435
PrefixFieldWithTableName = true;
1536

16-
var sourceDef = typeof(Source).GetModelDefinition();
17-
var targetDef = typeof(Target).GetModelDefinition();
37+
var sourceDef = typeof (Source).GetModelDefinition();
38+
var targetDef = typeof (Target).GetModelDefinition();
1839

1940
if (tableDefs.Count == 0)
2041
tableDefs.Add(modelDef);
@@ -34,19 +55,31 @@ public SqlExpression<T> Join<Source, Target>(Expression<Func<Source, Target, boo
3455
}
3556
else
3657
{
37-
var refField = OrmLiteReadExtensions.GetRefFieldDef(sourceDef, targetDef, typeof(Source));
58+
var parentDef = sourceDef;
59+
var childDef = targetDef;
60+
61+
var refField = OrmLiteReadExtensions.GetRefFieldDefIfExists(parentDef, childDef);
3862
if (refField == null)
63+
{
64+
parentDef = targetDef;
65+
childDef = sourceDef;
66+
refField = OrmLiteReadExtensions.GetRefFieldDefIfExists(parentDef, childDef);
67+
}
68+
69+
if (refField == null)
70+
{
3971
throw new ArgumentException("Could not infer relationship between {0} and {1}"
40-
.Fmt(sourceDef.ModelName, targetDef.ModelName));
72+
.Fmt(sourceDef.ModelName, targetDef.ModelName));
73+
}
4174

4275
sqlExpr = "\n({0}.{1} = {2}.{3})".Fmt(
43-
sourceDef.ModelName.SqlTable(),
44-
sourceDef.PrimaryKey.FieldName.SqlColumn(),
45-
targetDef.ModelName.SqlTable(),
76+
parentDef.ModelName.SqlTable(),
77+
parentDef.PrimaryKey.FieldName.SqlColumn(),
78+
childDef.ModelName.SqlTable(),
4679
refField.FieldName.SqlColumn());
4780
}
4881

49-
sbJoin.Append(" INNER JOIN {0} ".Fmt(targetDef.ModelName.SqlTable()));
82+
sbJoin.Append(" {0} {1} ".Fmt(joinType, targetDef.ModelName.SqlTable()));
5083
sbJoin.Append(" ON ");
5184
sbJoin.Append(sqlExpr);
5285

src/ServiceStack.OrmLite/OrmLiteReadExtensions.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -843,12 +843,18 @@ public static void LoadReferences<T>(this IDbCommand dbCmd, T instance)
843843
}
844844

845845
public static FieldDefinition GetRefFieldDef(ModelDefinition modelDef, ModelDefinition refModelDef, Type refType)
846+
{
847+
var refField = GetRefFieldDefIfExists(modelDef, refModelDef);
848+
if (refField == null)
849+
throw new ArgumentException("Cant find '{0}' Property on Type '{1}'".Fmt(modelDef.ModelName + "Id", refType.Name));
850+
return refField;
851+
}
852+
853+
public static FieldDefinition GetRefFieldDefIfExists(ModelDefinition modelDef, ModelDefinition refModelDef)
846854
{
847855
var refNameConvention = modelDef.ModelName + "Id";
848856
var refField = refModelDef.FieldDefinitions.FirstOrDefault(x => x.FieldName == refNameConvention)
849-
?? refModelDef.FieldDefinitions.FirstOrDefault(x => x.Name == modelDef.Name + "Id");
850-
if (refField == null)
851-
throw new ArgumentException("Cant find '{0}' Property on Type '{1}'".Fmt(refNameConvention, refType.Name));
857+
?? refModelDef.FieldDefinitions.FirstOrDefault(x => x.Name == modelDef.Name + "Id");
852858
return refField;
853859
}
854860
}

tests/ServiceStack.OrmLite.Tests/Expression/ExpressionChainingUseCase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ public void When_chaining_expressions_using_Where_it_behaves_like_And()
125125
visitor.Where(x => x.FirstName.StartsWith("M"));
126126
//WHERE (((upper("FirstName") like 'JIM%' AND upper("LastName") like 'HEN%' ) OR upper("FirstName") like 'M%' ) AND upper("FirstName") like 'M%' )
127127
results = db.Select(visitor);
128+
db.GetLastSql().Print();
128129
Assert.AreEqual(1, results.Count);
129130
}
130131

tests/ServiceStack.OrmLite.Tests/LoadReferencesTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,15 @@ public void Can_do_joins_with_wheres_using_SqlExpression()
402402
var costs = results.ConvertAll(x => x.Cost);
403403
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m }));
404404

405+
var orders = db.Select<Order>(q => q
406+
.Join<Order, Customer>()
407+
.Join<Customer, CustomerAddress>()
408+
.Where(o => o.Cost < 2)
409+
.And<Customer>(c => c.Name == "Customer 1"));
410+
411+
costs = orders.ConvertAll(x => x.Cost);
412+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m }));
413+
405414
results = db.Select<CustomerJoin, Customer>(q => q
406415
.Join<Customer, CustomerAddress>()
407416
.Join<Customer, Order>()

0 commit comments

Comments
 (0)