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

Commit 20827c6

Browse files
committed
Add support for custom Visiting for virtual propertiis in custom SqlExpression
1 parent 6d9e8d7 commit 20827c6

File tree

4 files changed

+144
-1
lines changed

4 files changed

+144
-1
lines changed

src/ServiceStack.OrmLite/Expressions/SqlExpression.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1363,7 +1363,19 @@ protected virtual object VisitBinary(BinaryExpression b)
13631363
}
13641364
else if (!(left is PartialSqlString) && !(right is PartialSqlString))
13651365
{
1366-
var evaluatedValue = CachedExpressionCompiler.Evaluate(b);
1366+
var visitedBinaryExp = b;
1367+
1368+
if (IsParameterAccess(b.Left) || IsParameterAccess(b.Right))
1369+
{
1370+
var eLeft = !IsParameterAccess(b.Left) ? b.Left : Expression.Constant(left, b.Left.Type);
1371+
var eRight = !IsParameterAccess(b.Right) ? b.Right : Expression.Constant(right, b.Right.Type);
1372+
if (b.NodeType == ExpressionType.Coalesce)
1373+
visitedBinaryExp = Expression.Coalesce(eLeft, eRight, b.Conversion);
1374+
else
1375+
visitedBinaryExp = Expression.MakeBinary(b.NodeType, eLeft, eRight, b.IsLiftedToNull, b.Method);
1376+
}
1377+
1378+
var evaluatedValue = CachedExpressionCompiler.Evaluate(visitedBinaryExp);
13671379
var result = VisitConstant(Expression.Constant(evaluatedValue));
13681380
return result;
13691381
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using System;
2+
using System.Data;
3+
using System.Linq.Expressions;
4+
using NUnit.Framework;
5+
using ServiceStack.OrmLite.Sqlite;
6+
7+
8+
namespace ServiceStack.OrmLite.Tests
9+
{
10+
public class Waybill
11+
{
12+
public int Id { get; set; }
13+
14+
public int Number { get; set; }
15+
16+
public string Name { get; set; }
17+
18+
public string VirtProperty => "WaybillVirtPropertyValue";
19+
}
20+
21+
public class CustomSqlServerDialectProvider : SqliteOrmLiteDialectProvider
22+
{
23+
public override SqlExpression<T> SqlExpression<T>()
24+
{
25+
return new CustomSqlExpression<T>(this);
26+
}
27+
}
28+
29+
public class CustomSqlExpression<T> : SqlExpression<T>
30+
{
31+
32+
public CustomSqlExpression(IOrmLiteDialectProvider dialectProvider) : base(dialectProvider)
33+
{
34+
}
35+
36+
protected override Object GetMemberExpression(MemberExpression m)
37+
{
38+
if (m.Member.DeclaringType == typeof(Waybill) &&
39+
m.Member.Name == nameof(Waybill.VirtProperty))
40+
{
41+
return "WaybillVirtPropertyValue";
42+
}
43+
44+
return base.GetMemberExpression(m);
45+
}
46+
}
47+
48+
[TestFixture]
49+
public class CustomSqlExpressionTests : OrmLiteTestBase
50+
{
51+
private IDbConnection Db;
52+
53+
[OneTimeSetUp]
54+
public void CustomInit()
55+
{
56+
ConnectionString = Config.SqliteMemoryDb;
57+
DbFactory = new OrmLiteConnectionFactory(ConnectionString, new CustomSqlServerDialectProvider());
58+
}
59+
60+
[SetUp]
61+
public void Setup()
62+
{
63+
using (var db = OpenDbConnection())
64+
{
65+
db.DropTable<Waybill>();
66+
67+
db.CreateTable<Waybill>();
68+
db.Insert(new Waybill {Id = 1, Number = 100, Name = "first"});
69+
db.Insert(new Waybill {Id = 2, Number = 200, Name = "second"});
70+
db.Insert(new Waybill {Id = 3, Number = 300, Name = "third"});
71+
}
72+
Db = OpenDbConnection();
73+
}
74+
75+
[TearDown]
76+
public void TearDown()
77+
{
78+
Db.Dispose();
79+
}
80+
81+
[Test]
82+
public void Can_Where_using_constant_filter1()
83+
{
84+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "WaybillVirtPropertyValue";
85+
var q = Db.From<Waybill>().Where(filter);
86+
var target = Db.Select(q);
87+
Assert.AreEqual(3, target.Count);
88+
}
89+
90+
[Test]
91+
public void Can_Where_using_constant_filter2()
92+
{
93+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "Any";
94+
var q = Db.From<Waybill>().Where(filter);
95+
var target = Db.Select(q);
96+
Assert.AreEqual(0, target.Count);
97+
}
98+
99+
[Test]
100+
public void Can_Where_using_constant_filter3()
101+
{
102+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty != "WaybillVirtPropertyValue";
103+
var q = Db.From<Waybill>().Where(filter);
104+
var target = Db.Select(q);
105+
Assert.AreEqual(0, target.Count);
106+
}
107+
108+
[Test]
109+
public void Can_Where_using_constant_filter4()
110+
{
111+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty != "Any";
112+
var q = Db.From<Waybill>().Where(filter);
113+
var target = Db.Select(q);
114+
Assert.AreEqual(3, target.Count);
115+
}
116+
}
117+
}

tests/ServiceStack.OrmLite.Tests/ExpressionVisitorTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,19 @@ public void Can_Where_using_filter_with_Concat()
489489
Assert.That(target.Count, Is.EqualTo(1));
490490
}
491491

492+
[Test]
493+
public void Can_Where_using_constant_filter()
494+
{
495+
object left = null;
496+
var right = new PartialSqlString("null");
497+
498+
System.Linq.Expressions.Expression<Func<TestType, bool>> filter = x => left == right;
499+
var q = Db.From<TestType>().Where(filter);//todo: here Where: null is NULL. May be need to change to 1=1 ?
500+
var target = Db.Select(q);
501+
Assert.That(target.Count, Is.EqualTo(4));
502+
503+
}
504+
492505
private int MethodReturningInt(int val)
493506
{
494507
return val;

tests/ServiceStack.OrmLite.Tests/ServiceStack.OrmLite.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
<Compile Include="Async\SqlExpressionTests.cs" />
137137
<Compile Include="Async\SqlServerProviderTestsAsync.cs" />
138138
<Compile Include="Async\UpdateAsyncTests.cs" />
139+
<Compile Include="CustomSqlExpressionTests.cs" />
139140
<Compile Include="Expression\JoinAliasTests.cs" />
140141
<Compile Include="Expression\RestrictionTests.cs" />
141142
<Compile Include="Expression\SqlExpressionDeleteTests.cs" />

0 commit comments

Comments
 (0)