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

Commit 71e14c0

Browse files
committed
Write test to demonstrate Oracle provider problem with profiler and fix provider.
1 parent 7475c79 commit 71e14c0

File tree

4 files changed

+122
-8
lines changed

4 files changed

+122
-8
lines changed

src/ServiceStack.OrmLite.Oracle.Tests/ServiceStack.OrmLite.Oracle.Tests.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
<SpecificVersion>False</SpecificVersion>
5353
<HintPath>..\..\lib\tests\nunit.framework.dll</HintPath>
5454
</Reference>
55+
<Reference Include="ServiceStack">
56+
<HintPath>..\..\lib\ServiceStack.dll</HintPath>
57+
</Reference>
5558
<Reference Include="ServiceStack.Common">
5659
<HintPath>..\..\lib\ServiceStack.Common.dll</HintPath>
5760
</Reference>
@@ -321,6 +324,9 @@
321324
<Compile Include="..\GlobalAssemblyInfo.cs">
322325
<Link>Properties\GlobalAssemblyInfo.cs</Link>
323326
</Compile>
327+
<Compile Include="WrappedCommandTests.cs">
328+
<SubType>Component</SubType>
329+
</Compile>
324330
<Compile Include="DateTimeColumnTest.cs" />
325331
<Compile Include="ForeignKeyAttributeTests.cs" />
326332
<Compile Include="OracleParamTests.cs">
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System.Data;
2+
using System.Data.Common;
3+
using NUnit.Framework;
4+
using ServiceStack.MiniProfiler;
5+
using ServiceStack.MiniProfiler.Data;
6+
using ServiceStack.OrmLite.Oracle;
7+
8+
namespace ServiceStack.OrmLite.Tests
9+
{
10+
[TestFixture]
11+
public class WrappedCommandTests : OrmLiteTestBase
12+
{
13+
[Test]
14+
public void WrappingWithMiniProfilerSucceeds()
15+
{
16+
var factory = new OrmLiteConnectionFactory(ConnectionString, OracleDialect.Provider)
17+
{
18+
ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current)
19+
};
20+
21+
using (var db = factory.OpenDbConnection())
22+
{
23+
DoInsertUpdate(db);
24+
}
25+
}
26+
27+
private static void DoInsertUpdate(IDbConnection db)
28+
{
29+
db.CreateTable<ParamPassword>(true);
30+
31+
var row = new ParamPassword { Id = 2, Password = 6 };
32+
db.Insert(row);
33+
34+
row.Password = 335;
35+
db.Update(row);
36+
}
37+
38+
[Test]
39+
public void WrappingWithSpecializedMiniProfilerSucceeds()
40+
{
41+
var factory = new OrmLiteConnectionFactory(ConnectionString, OracleDialect.Provider)
42+
{
43+
ConnectionFilter = x => new SpecializedProfiledDbConnection(x, Profiler.Current)
44+
};
45+
46+
using (var db = factory.OpenDbConnection())
47+
{
48+
DoInsertUpdate(db);
49+
}
50+
}
51+
}
52+
53+
public class ParamPassword
54+
{
55+
public int Id { get; set; }
56+
public int Password { get; set; }
57+
}
58+
59+
public class SpecializedProfiledDbConnection : ProfiledDbConnection
60+
{
61+
public SpecializedProfiledDbConnection(DbConnection connection, IDbProfiler profiler, bool autoDisposeConnection = true)
62+
: base(connection, profiler, autoDisposeConnection)
63+
{ }
64+
65+
public SpecializedProfiledDbConnection(IDbConnection connection, IDbProfiler profiler, bool autoDisposeConnection = true)
66+
: base(connection, profiler, autoDisposeConnection)
67+
{ }
68+
69+
protected override DbCommand CreateDbCommand()
70+
{
71+
return new SpecializedProfiledDbCommand(InnerConnection.CreateCommand(), InnerConnection, Profiler);
72+
}
73+
}
74+
75+
public class SpecializedProfiledDbCommand : ProfiledDbCommand
76+
{
77+
public SpecializedProfiledDbCommand(DbCommand cmd, DbConnection conn, IDbProfiler profiler)
78+
: base(cmd, conn, profiler)
79+
{ }
80+
}
81+
}
Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Data;
4+
using System.Reflection;
5+
using System.Reflection.Emit;
36

47
namespace ServiceStack.OrmLite.Oracle
58
{
@@ -9,16 +12,37 @@ public override IDbCommand CreateCommand(IDbConnection dbConn)
912
{
1013
var command = base.CreateCommand(dbConn);
1114

12-
// Doing comparison and set this way to avoid having a reference to the Oracle client
13-
// so that customers can use a different version than we used to compile without
14-
// requiring a version redirect in a config file somewhere.
15-
var commandType = command.GetType();
16-
if (commandType.FullName.StartsWith("Oracle.DataAccess.Client", StringComparison.InvariantCulture))
15+
var action = GetBindByNameSetter(command.GetType());
16+
if (action != null) action(command, true);
17+
18+
return command;
19+
}
20+
21+
private static readonly Dictionary<Type, Action<IDbCommand, bool>> Cache = new Dictionary<Type, Action<IDbCommand, bool>>();
22+
private static Action<IDbCommand, bool> GetBindByNameSetter(Type commandType)
23+
{
24+
if (commandType == null) return null;
25+
26+
Action<IDbCommand, bool> action;
27+
if (Cache.TryGetValue(commandType, out action)) return action;
28+
29+
var prop = commandType.GetProperty("BindByName", BindingFlags.Public | BindingFlags.Instance);
30+
MethodInfo setter;
31+
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(bool)
32+
&& prop.GetIndexParameters().Length == 0 && (setter = prop.GetSetMethod()) != null)
1733
{
18-
var pi = commandType.GetProperty("BindByName");
19-
pi.SetValue(command, true, null);
34+
var methodName = commandType.GetOperationName() + "_BindByName";
35+
var method = new DynamicMethod(methodName, null, new []{ typeof(IDbCommand), typeof(bool) });
36+
var il = method.GetILGenerator();
37+
il.Emit(OpCodes.Ldarg_0);
38+
il.Emit(OpCodes.Castclass, commandType);
39+
il.Emit(OpCodes.Ldarg_1);
40+
il.EmitCall(OpCodes.Callvirt, setter, null);
41+
il.Emit(OpCodes.Ret);
42+
action = (Action<IDbCommand, bool>)method.CreateDelegate(typeof(Action<IDbCommand, bool>));
2043
}
21-
return command;
44+
Cache.Add(commandType, action);
45+
return action;
2246
}
2347
}
2448
}

src/ServiceStack.OrmLite.Oracle/ServiceStack.OrmLite.Oracle.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
4242
</PropertyGroup>
4343
<ItemGroup>
44+
<Reference Include="ServiceStack.Client">
45+
<HintPath>..\..\lib\ServiceStack.Client.dll</HintPath>
46+
</Reference>
4447
<Reference Include="ServiceStack.Text">
4548
<HintPath>..\..\lib\ServiceStack.Text.dll</HintPath>
4649
</Reference>

0 commit comments

Comments
 (0)