Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added UseSharedConnection to AdoAdapter

  • Loading branch information...
commit 504a9f5d32dc0461229250c2930522a18029c52d 1 parent 19d2602
@markrendle authored
Showing with 297 additions and 80 deletions.
  1. +2 −2 CommonAssemblyInfo.cs
  2. +102 −0 PerformanceTestConsole.psess
  3. +11 −12 PerformanceTestConsole/PerformanceTestConsole.csproj
  4. +7 −4 PerformanceTestConsole/Program.cs
  5. BIN  PerformanceTestConsole111123.vsp
  6. +3 −2 ProfilingApp/FindByTask.cs
  7. +1 −1  ProfilingApp/Program.cs
  8. +14 −2 Simple.Data.Ado/AdoAdapter.cs
  9. +11 −3 Simple.Data.Ado/AdoAdapterFinder.cs
  10. +6 −3 Simple.Data.Ado/AdoAdapterInserter.cs
  11. +6 −3 Simple.Data.Ado/BulkInserterHelper.cs
  12. +3 −2 Simple.Data.Ado/BulkUpdater.cs
  13. +18 −0 Simple.Data.Ado/ConnectionEx.cs
  14. +3 −1 Simple.Data.Ado/DataReaderMultipleEnumerator.cs
  15. +4 −1 Simple.Data.Ado/FindHelper.cs
  16. +1 −0  Simple.Data.Ado/Simple.Data.Ado.csproj
  17. +22 −21 Simple.Data.BehaviourTest/FindTest.cs
  18. +2 −2 Simple.Data.BehaviourTest/NameResolutionTests.cs
  19. +1 −1  Simple.Data.BehaviourTest/NaturalJoinTest.cs
  20. +1 −1  Simple.Data.BehaviourTest/NaturalNamingTest.cs
  21. +3 −1 Simple.Data.BehaviourTest/Query/FunctionTest.cs
  22. +9 −8 Simple.Data.BehaviourTest/SchemaQualifiedTableTest.cs
  23. +4 −2 Simple.Data.BehaviourTest/TransactionTest.cs
  24. +2 −1  Simple.Data.SqlServer/SqlCommandOptimizer.cs
  25. +6 −1 Simple.Data/ActionDisposable.cs
  26. +29 −4 Simple.Data/DynamicTable.cs
  27. +26 −2 Simple.Data/FunctionSignature.cs
View
4 CommonAssemblyInfo.cs
@@ -19,6 +19,6 @@
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
-[assembly: AssemblyVersion("0.10.2.1")]
-[assembly: AssemblyFileVersion("0.10.2.1")]
+[assembly: AssemblyVersion("0.11.0.1")]
+[assembly: AssemblyFileVersion("0.11.0.1")]
View
102 PerformanceTestConsole.psess
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VSPerformanceSession Version="1.00">
+ <Options>
+ <Solution>D:\Code\Simple.Data\Simple.Data.sln</Solution>
+ <CollectionMethod>Instrumentation</CollectionMethod>
+ <AllocationMethod>None</AllocationMethod>
+ <LaunchRuntimeControl>true</LaunchRuntimeControl>
+ <AddReport>true</AddReport>
+ <ResourceBasedAnalysisSelected>false</ResourceBasedAnalysisSelected>
+ <ThreadBasedAnalysisSelected>false</ThreadBasedAnalysisSelected>
+ <UniqueReport>Timestamp</UniqueReport>
+ <SamplingMethod>Cycles</SamplingMethod>
+ <CycleCount>10000000</CycleCount>
+ <PageFaultCount>10</PageFaultCount>
+ <SysCallCount>10</SysCallCount>
+ <SamplingCounter Name="" ReloadValue="00000000000f4240" DisplayName="" />
+ <RelocateBinaries>false</RelocateBinaries>
+ <CollectOnHpcCluster>false</CollectOnHpcCluster>
+ <HPCSettings>
+ <NumberOfProcesses>0</NumberOfProcesses>
+ <TargetSelection>UnknownDisabled</TargetSelection>
+ <ProfileOnRank>0</ProfileOnRank>
+ <AdvancedProperties>
+ <Project>PerformanceTestConsole</Project>
+ <CleanUp>true</CleanUp>
+ <MpiexecCommand>mpiexec.exe</MpiexecCommand>
+ <DeployCRT>true</DeployCRT>
+ </AdvancedProperties>
+ </HPCSettings>
+ <HardwareCounters EnableHWCounters="false" />
+ <EtwSettings />
+ <PdhSettings>
+ <PdhCountersEnabled>false</PdhCountersEnabled>
+ <PdhCountersRate>500</PdhCountersRate>
+ <PdhCounters>
+ <PdhCounter>\Memory\Pages/sec</PdhCounter>
+ <PdhCounter>\PhysicalDisk(_Total)\Avg. Disk Queue Length</PdhCounter>
+ <PdhCounter>\Processor(_Total)\% Processor Time</PdhCounter>
+ </PdhCounters>
+ </PdhSettings>
+ </Options>
+ <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
+ <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
+ <PreinstrumentEvent>
+ <InstrEventExclude>false</InstrEventExclude>
+ </PreinstrumentEvent>
+ <PostinstrumentEvent>
+ <InstrEventExclude>false</InstrEventExclude>
+ </PostinstrumentEvent>
+ <Binaries>
+ <ProjBinary>
+ <Path>D:\Code\Simple.Data\PerformanceTestConsole\obj\x86\Debug\PerformanceTestConsole.exe</Path>
+ <ArgumentTimestamp>01/01/0001 00:00:00</ArgumentTimestamp>
+ <Instrument>true</Instrument>
+ <Sample>true</Sample>
+ <ExternalWebsite>false</ExternalWebsite>
+ <InteractionProfilingEnabled>false</InteractionProfilingEnabled>
+ <IsLocalJavascript>false</IsLocalJavascript>
+ <LaunchProject>true</LaunchProject>
+ <OverrideProjectSettings>false</OverrideProjectSettings>
+ <LaunchMethod>Executable</LaunchMethod>
+ <ExecutablePath>D:\Code\Simple.Data\PerformanceTestConsole\bin\Debug\PerformanceTestConsole.exe</ExecutablePath>
+ <StartupDirectory>D:\Code\Simple.Data\PerformanceTestConsole\bin\Debug\</StartupDirectory>
+ <Arguments />
+ <NetAppHost>IIS</NetAppHost>
+ <NetBrowser>InternetExplorer</NetBrowser>
+ <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
+ <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
+ <PreinstrumentEvent>
+ <InstrEventExclude>false</InstrEventExclude>
+ </PreinstrumentEvent>
+ <PostinstrumentEvent>
+ <InstrEventExclude>false</InstrEventExclude>
+ </PostinstrumentEvent>
+ <ProjRef>{C88EA51F-59C4-4283-97AC-06440F4AA4F6}|PerformanceTestConsole\PerformanceTestConsole.csproj</ProjRef>
+ <ProjPath>D:\Code\Simple.Data\PerformanceTestConsole\PerformanceTestConsole.csproj</ProjPath>
+ <ProjName>PerformanceTestConsole</ProjName>
+ </ProjBinary>
+ </Binaries>
+ <Reports>
+ <Report>
+ <Path>D:\Code\Simple.Data\PerformanceTestConsole111123.vsp</Path>
+ </Report>
+ </Reports>
+ <Launches>
+ <ProjBinary>
+ <Path>:PB:{C88EA51F-59C4-4283-97AC-06440F4AA4F6}|PerformanceTestConsole\PerformanceTestConsole.csproj</Path>
+ </ProjBinary>
+ </Launches>
+ <RuntimeMarks>
+ <MarkName>Mark One</MarkName>
+ <MarkName>Mark Two</MarkName>
+ <MarkName>Mark Three</MarkName>
+ <MarkName>Mark Four</MarkName>
+ <MarkName>Mark Five</MarkName>
+ <MarkName>Mark Six</MarkName>
+ <MarkName>Mark Seven</MarkName>
+ <MarkName>Mark Eight</MarkName>
+ <MarkName>Mark Nine</MarkName>
+ <MarkName>Mark Ten</MarkName>
+ </RuntimeMarks>
+</VSPerformanceSession>
View
23 PerformanceTestConsole/PerformanceTestConsole.csproj
@@ -34,15 +34,6 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
- <Reference Include="Simple.Data, Version=0.6.1.0, Culture=neutral, processorArchitecture=MSIL">
- <HintPath>..\packages\Simple.Data.Core.0.6.1\lib\net40\Simple.Data.dll</HintPath>
- </Reference>
- <Reference Include="Simple.Data.Ado, Version=0.6.1.0, Culture=neutral, processorArchitecture=MSIL">
- <HintPath>..\packages\Simple.Data.Ado.0.6.1\lib\net40\Simple.Data.Ado.dll</HintPath>
- </Reference>
- <Reference Include="Simple.Data.SqlCe40">
- <HintPath>..\packages\Simple.Data.SqlCompact40.0.6.1\lib\net40\Simple.Data.SqlCe40.dll</HintPath>
- </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@@ -56,13 +47,21 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Simple.Data.Ado\Simple.Data.Ado.csproj">
+ <Project>{ECC2D7DB-EC7F-44B6-B09F-5B471C629685}</Project>
+ <Name>Simple.Data.Ado</Name>
+ </ProjectReference>
<ProjectReference Include="..\Simple.Data.SqlServer\Simple.Data.SqlServer.csproj">
<Project>{E24F1C0F-3DCD-4BE5-9A6E-78EF6CB392A1}</Project>
<Name>Simple.Data.SqlServer</Name>
</ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
+ <ProjectReference Include="..\Simple.Data\Simple.Data.csproj">
+ <Project>{148CEE80-2E84-4ABD-B5AB-20415B2BBD21}</Project>
+ <Name>Simple.Data</Name>
+ </ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
View
11 PerformanceTestConsole/Program.cs
@@ -8,6 +8,8 @@
namespace PerformanceTestConsole
{
+ using Simple.Data.Ado;
+
class Post
{
public int Id { get; set; }
@@ -29,11 +31,11 @@ class Post
class Program
{
- public static readonly string connectionString = "Data Source=SQL2008;Initial Catalog=tempdb;User ID=sa;Password=SAPassword01";
+ public static readonly string ConnectionString = "Data Source=.;Initial Catalog=tempdb;Integrated Security=true";
public static SqlConnection GetOpenConnection()
{
- var connection = new SqlConnection(connectionString);
+ var connection = new SqlConnection(ConnectionString);
connection.Open();
return connection;
}
@@ -166,7 +168,8 @@ public void Run(int iterations)
public void Run(int iterations)
{
var tests = new Tests();
- var simpleDb = Simple.Data.Database.OpenConnection(Program.connectionString);
+ var simpleDb = Simple.Data.Database.OpenConnection(Program.ConnectionString);
+ ((AdoAdapter)simpleDb.GetAdapter()).UseSharedConnection(Program.GetOpenConnection());
simpleDb.Posts.FindById(1);
tests.Add(id => simpleDb.Posts.FindById(id), "Dynamic Simple.Data Query");
@@ -176,7 +179,7 @@ public void Run(int iterations)
var postCommand = new SqlCommand();
postCommand.Connection = connection;
- postCommand.CommandText = @"select Id, [Text], [CreationDate], LastChangeDate,
+ postCommand.CommandText = @"select top 1 Id, [Text], [CreationDate], LastChangeDate,
Counter1,Counter2,Counter3,Counter4,Counter5,Counter6,Counter7,Counter8,Counter9 from Posts where Id = @Id";
var idParam = postCommand.Parameters.Add("@Id", System.Data.SqlDbType.Int);
View
BIN  PerformanceTestConsole111123.vsp
Binary file not shown
View
5 ProfilingApp/FindByTask.cs
@@ -9,6 +9,7 @@ namespace ProfilingApp
class FindByTask : IProfileTask
{
+ private readonly dynamic _db = Database.OpenConnection(Properties.Settings.Default.ConnectionString);
public void Run()
{
for (int i = 1; i < 101; i++)
@@ -17,9 +18,9 @@ public void Run()
}
}
- private static void GetPostAndPrintTitle(int i)
+ private void GetPostAndPrintTitle(int i)
{
- var post = Database.OpenConnection(Properties.Settings.Default.ConnectionString).Posts.FindById(i);
+ var post = _db.Posts.FindById(i);
Console.WriteLine(post.Title);
}
}
View
2  ProfilingApp/Program.cs
@@ -14,7 +14,7 @@ static void Main(string[] args)
{
ResetDatabase();
- new QueryWithCountTask().Run();
+ new FindByTask().Run();
}
private static void ResetDatabase()
View
16 Simple.Data.Ado/AdoAdapter.cs
@@ -39,6 +39,7 @@ public IConnectionProvider ConnectionProvider
private DatabaseSchema _schema;
private Lazy<AdoAdapterRelatedFinder> _relatedFinder;
+ private IDbConnection _sharedConnection;
public AdoAdapter()
{
@@ -355,7 +356,8 @@ public IEnumerable<string> GetKeyFieldNames(string tableName)
private int Execute(ICommandBuilder commandBuilder)
{
- using (var connection = CreateConnection())
+ var connection = CreateConnection();
+ using (connection.MaybeDisposable())
{
using (var command = commandBuilder.GetCommand(connection))
{
@@ -388,9 +390,19 @@ private static int TryExecute(IDbCommand command)
}
}
+ public void UseSharedConnection(IDbConnection connection)
+ {
+ _sharedConnection = connection;
+ }
+
+ public void StopUsingSharedConnection()
+ {
+ _sharedConnection = null;
+ }
+
internal IDbConnection CreateConnection()
{
- return _connectionProvider.CreateConnection();
+ return _sharedConnection ?? _connectionProvider.CreateConnection();
}
internal DatabaseSchema GetSchema()
View
14 Simple.Data.Ado/AdoAdapterFinder.cs
@@ -5,7 +5,6 @@
using System.Data.Common;
using System.Linq;
using System.Text;
-using Simple.Data.Ado.Schema;
namespace Simple.Data.Ado
{
@@ -19,7 +18,6 @@ class AdoAdapterFinder
private readonly AdoAdapter _adapter;
private readonly IDbTransaction _transaction;
private readonly IDbConnection _connection;
- private readonly DatabaseSchema _schema;
public AdoAdapterFinder(AdoAdapter adapter) : this(adapter, null)
{
@@ -157,7 +155,7 @@ private CommandTemplate GetCommandTemplate(string tableName, SimpleExpression cr
private static IDictionary<string, object> TryExecuteSingletonQuery(IDbConnection connection, IDbCommand command, IDictionary<string, int> index)
{
command.WriteTrace();
- using (connection)
+ using (connection.MaybeDisposable())
using (command)
{
try
@@ -180,6 +178,16 @@ private CommandTemplate GetCommandTemplate(string tableName, SimpleExpression cr
return null;
}
+ private static IDisposable DisposeWrap(IDbConnection connection)
+ {
+ if (connection.State == ConnectionState.Open)
+ {
+ return ActionDisposable.NoOp;
+ }
+
+ return new ActionDisposable(connection.Dispose);
+ }
+
private static object FixObjectType(object value)
{
if (value == null) return DBNull.Value;
View
9 Simple.Data.Ado/AdoAdapterInserter.cs
@@ -103,7 +103,8 @@ private void CheckInsertablePropertiesAreAvailable(Table table, IEnumerable<KeyV
return TryExecuteSingletonQuery(command);
}
- using (var connection = _adapter.CreateConnection())
+ var connection = _adapter.CreateConnection();
+ using (connection.MaybeDisposable())
{
using (var command = new CommandHelper(_adapter).CreateInsert(connection, sql, columns, values.ToArray()))
{
@@ -125,7 +126,8 @@ private void CheckInsertablePropertiesAreAvailable(Table table, IEnumerable<KeyV
return TryExecuteSingletonQuery(command);
}
- using (var connection = _adapter.CreateConnection())
+ var connection = _adapter.CreateConnection();
+ using (connection.MaybeDisposable())
{
using (var command = new CommandHelper(_adapter).CreateInsert(connection, insertSql, columns, values.ToArray()))
{
@@ -167,7 +169,8 @@ internal int Execute(string sql, IEnumerable<Column> columns, IEnumerable<Object
command.Transaction = _transaction;
return TryExecute(command);
}
- using (var connection = _adapter.CreateConnection())
+ var connection = _adapter.CreateConnection();
+ using (connection.MaybeDisposable())
{
using (var command = new CommandHelper(_adapter).CreateInsert(connection, sql, columns, values.ToArray()))
{
View
9 Simple.Data.Ado/BulkInserterHelper.cs
@@ -25,7 +25,8 @@ public BulkInserterHelper(AdoAdapter adapter, IEnumerable<IDictionary<string, ob
public virtual void InsertRowsWithoutFetchBack(string insertSql)
{
- using (var connection = Adapter.CreateConnection())
+ var connection = Adapter.CreateConnection();
+ using (connection.MaybeDisposable())
{
using (var insertCommand = new CommandHelper(Adapter).CreateInsert(connection, insertSql, _columns))
{
@@ -42,7 +43,8 @@ public virtual void InsertRowsWithoutFetchBack(string insertSql)
public virtual IEnumerable<IDictionary<string, object>> InsertRowsWithSeparateStatements(string insertSql, string selectSql)
{
- using (var connection = Adapter.CreateConnection())
+ var connection = Adapter.CreateConnection();
+ using (connection.MaybeDisposable())
{
using (var insertCommand = new CommandHelper(Adapter).CreateInsert(connection, insertSql, _columns))
using (var selectCommand = connection.CreateCommand())
@@ -59,7 +61,8 @@ public virtual void InsertRowsWithoutFetchBack(string insertSql)
{
insertSql += "; " + selectSql;
- using (var connection = Adapter.CreateConnection())
+ var connection = Adapter.CreateConnection();
+ using (connection.MaybeDisposable())
{
using (var command = new CommandHelper(Adapter).CreateInsert(connection, insertSql, _columns))
{
View
5 Simple.Data.Ado/BulkUpdater.cs
@@ -33,8 +33,9 @@ public int Update(AdoAdapter adapter, string tableName, IList<IDictionary<string
ExpressionHelper.CriteriaDictionaryToExpression(
tableName, GetCriteria(criteriaFieldNameList, exampleRow)));
- using (var connectionScope = ConnectionScope.Create(transaction, adapter.CreateConnection))
- using (var command = commandBuilder.GetRepeatableCommand(connectionScope.Connection))
+ var connection = adapter.CreateConnection();
+ using (connection.MaybeDisposable())
+ using (var command = commandBuilder.GetRepeatableCommand(connection))
{
var propertyToParameterMap = CreatePropertyToParameterMap(data, table, command);
View
18 Simple.Data.Ado/ConnectionEx.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Simple.Data.Ado
+{
+ using System.Data;
+
+ public static class ConnectionEx
+ {
+ public static IDisposable MaybeDisposable(this IDbConnection connection)
+ {
+ if (connection.State == ConnectionState.Open) return ActionDisposable.NoOp;
+ return new ActionDisposable(connection.Dispose);
+ }
+ }
+}
View
4 Simple.Data.Ado/DataReaderMultipleEnumerator.cs
@@ -8,6 +8,7 @@ namespace Simple.Data.Ado
class DataReaderMultipleEnumerator : IEnumerator<IEnumerable<IDictionary<string, object>>>
{
+ private readonly IDisposable _connectionDisposable;
private readonly IDbConnection _connection;
private IDictionary<string, int> _index;
private readonly IDbCommand _command;
@@ -22,12 +23,13 @@ public DataReaderMultipleEnumerator(IDbCommand command, IDbConnection connection
{
_command = command;
_connection = connection;
+ _connectionDisposable = _connection.MaybeDisposable();
_index = index;
}
public void Dispose()
{
- using (_connection)
+ using (_connectionDisposable)
using (_command)
using (_reader)
{
View
5 Simple.Data.Ado/FindHelper.cs
@@ -5,6 +5,8 @@
namespace Simple.Data.Ado
{
+ using System.Linq;
+
internal class FindHelper
{
private readonly DatabaseSchema _schema;
@@ -35,7 +37,8 @@ public ICommandBuilder GetFindByCommand(ObjectName tableName, SimpleExpression c
private string GetSelectClause(ObjectName tableName)
{
- return string.Format("select {0}.* from {0}", _schema.FindTable(tableName).QualifiedName);
+ var table = _schema.FindTable(tableName);
+ return string.Format("select {0} from {1}", string.Join(", ", table.Columns.Select(c => c.QualifiedName)), table.QualifiedName);
}
}
}
View
1  Simple.Data.Ado/Simple.Data.Ado.csproj
@@ -59,6 +59,7 @@
<Compile Include="CommandBuilder.cs" />
<Compile Include="CommandHelper.cs" />
<Compile Include="CommandTemplate.cs" />
+ <Compile Include="ConnectionEx.cs" />
<Compile Include="ConnectionScope.cs" />
<Compile Include="DatabaseObservable.cs" />
<Compile Include="DataParameterCollectionEx.cs" />
View
43 Simple.Data.BehaviourTest/FindTest.cs
@@ -20,11 +20,12 @@ protected override void SetSchema(MockSchemaProvider schemaProvider)
schemaProvider.SetPrimaryKeys(new object[] { "dbo", "Users", "Id", 0 });
}
+ private const string usersColumns = "[dbo].[Users].[Id], [dbo].[Users].[Name], [dbo].[Users].[Password], [dbo].[Users].[Age]";
[Test]
public void TestFindEqualWithInt32()
{
_db.Users.Find(_db.Users.Id == 1);
- GeneratedSqlIs("select [dbo].[users].* from [dbo].[users] where [dbo].[users].[id] = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[users] where [dbo].[users].[id] = @p1");
Parameter(0).Is(1);
}
@@ -32,14 +33,14 @@ public void TestFindEqualWithInt32()
public void TestFindWithNull()
{
_db.Users.Find(_db.Users.Id == null);
- GeneratedSqlIs("select [dbo].[users].* from [dbo].[users] where [dbo].[users].[id] IS NULL");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[users] where [dbo].[users].[id] IS NULL");
}
[Test]
public void TestFindWithTwoCriteriasOneBeingNull()
{
_db.Users.Find(_db.Users.Id == 1 || _db.Users.Id == null);
- GeneratedSqlIs("select [dbo].[users].* from [dbo].[users] where ([dbo].[users].[id] = @p1 OR [dbo].[users].[id] IS NULL)");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[users] where ([dbo].[users].[id] = @p1 OR [dbo].[users].[id] IS NULL)");
Parameter(0).Is(1);
Parameter(1).DoesNotExist();
}
@@ -48,7 +49,7 @@ public void TestFindWithTwoCriteriasOneBeingNull()
public void TestFindNotEqualWithInt32()
{
_db.Users.Find(_db.Users.Id != 1);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] != @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] != @p1");
Parameter(0).Is(1);
}
@@ -56,7 +57,7 @@ public void TestFindNotEqualWithInt32()
public void TestFindGreaterThanWithInt32()
{
_db.Users.Find(_db.Users.Id > 1);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] > @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] > @p1");
Parameter(0).Is(1);
}
@@ -64,7 +65,7 @@ public void TestFindGreaterThanWithInt32()
public void TestFindGreaterThanOrEqualWithInt32()
{
_db.Users.Find(_db.Users.Id >= 1);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] >= @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] >= @p1");
Parameter(0).Is(1);
}
@@ -72,7 +73,7 @@ public void TestFindGreaterThanOrEqualWithInt32()
public void TestFindLessThanWithInt32()
{
_db.Users.Find(_db.Users.Id < 1);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] < @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] < @p1");
Parameter(0).Is(1);
}
@@ -80,7 +81,7 @@ public void TestFindLessThanWithInt32()
public void TestFindLessThanOrEqualWithInt32()
{
_db.Users.Find(_db.Users.Id <= 1);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] <= @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] <= @p1");
Parameter(0).Is(1);
}
@@ -88,7 +89,7 @@ public void TestFindLessThanOrEqualWithInt32()
public void TestFindModulo()
{
_db.Users.Find(_db.Users.Id % 2 == 1);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] % 2 = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] % 2 = @p1");
Parameter(0).Is(1);
}
@@ -96,7 +97,7 @@ public void TestFindModulo()
public void TestFindWithAdd()
{
_db.Users.Find(_db.Users.Id + _db.Users.Age == 42);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] + [dbo].[Users].[Age] = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] + [dbo].[Users].[Age] = @p1");
Parameter(0).Is(42);
}
@@ -104,7 +105,7 @@ public void TestFindWithAdd()
public void TestFindWithSubtract()
{
_db.Users.Find(_db.Users.Id - _db.Users.Age == 42);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] - [dbo].[Users].[Age] = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] - [dbo].[Users].[Age] = @p1");
Parameter(0).Is(42);
}
@@ -112,7 +113,7 @@ public void TestFindWithSubtract()
public void TestFindWithMultiply()
{
_db.Users.Find(_db.Users.Id * _db.Users.Age == 42);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] * [dbo].[Users].[Age] = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] * [dbo].[Users].[Age] = @p1");
Parameter(0).Is(42);
}
@@ -120,7 +121,7 @@ public void TestFindWithMultiply()
public void TestFindWithDivide()
{
_db.Users.Find(_db.Users.Id / _db.Users.Age == 42);
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[Id] / [dbo].[Users].[Age] = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[Id] / [dbo].[Users].[Age] = @p1");
Parameter(0).Is(42);
}
@@ -128,7 +129,7 @@ public void TestFindWithDivide()
public void TestFindByNamedParameterSingleColumn()
{
_db.Users.FindBy(Name: "Foo");
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[name] = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[name] = @p1");
Parameter(0).Is("Foo");
}
@@ -136,7 +137,7 @@ public void TestFindByNamedParameterSingleColumn()
public void TestFindByNamedParameterTwoColumns()
{
_db.Users.FindBy(Name: "Foo", Password: "password");
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where ([dbo].[Users].[name] = @p1 and [dbo].[Users].[password] = @p2)");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where ([dbo].[Users].[name] = @p1 and [dbo].[Users].[password] = @p2)");
Parameter(0).Is("Foo");
Parameter(1).Is("password");
}
@@ -145,7 +146,7 @@ public void TestFindByNamedParameterTwoColumns()
public void TestFindByDynamicSingleColumn()
{
_db.Users.FindByName("Foo");
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[name] = @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[name] = @p1");
Parameter(0).Is("Foo");
}
@@ -153,7 +154,7 @@ public void TestFindByDynamicSingleColumn()
public void TestFindByDynamicSingleColumnNull()
{
_db.MyTable.FindByColumn1(null);
- GeneratedSqlIs("select [dbo].[MyTable].* from [dbo].[MyTable] where [dbo].[MyTable].[Column1] is null");
+ GeneratedSqlIs("select [dbo].[MyTable].[Column1] from [dbo].[MyTable] where [dbo].[MyTable].[Column1] is null");
}
[Test]
@@ -167,7 +168,7 @@ public void TestFindAllByDynamicSingleColumnNull()
public void TestFindByWithAnonymousObject()
{
_db.MyTable.FindBy(new { Column1 = 1 });
- GeneratedSqlIs("select [dbo].[MyTable].* from [dbo].[MyTable] where [dbo].[MyTable].[Column1] = @p1");
+ GeneratedSqlIs("select [dbo].[MyTable].[Column1] from [dbo].[MyTable] where [dbo].[MyTable].[Column1] = @p1");
Parameter(0).Is(1);
}
@@ -175,14 +176,14 @@ public void TestFindByWithAnonymousObject()
public void TestFindByWithAnonymousObjectNullValue()
{
_db.MyTable.FindBy(new { Column1 = (object)null });
- GeneratedSqlIs("select [dbo].[MyTable].* from [dbo].[MyTable] where [dbo].[MyTable].[Column1] is null");
+ GeneratedSqlIs("select [dbo].[MyTable].[Column1] from [dbo].[MyTable] where [dbo].[MyTable].[Column1] is null");
}
[Test]
public void TestFindWithLike()
{
_db.Users.Find(_db.Users.Name.Like("Foo"));
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[name] like @p1");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[name] like @p1");
Parameter(0).Is("Foo");
}
@@ -216,7 +217,7 @@ public void TestFindAllByNamedParameterTwoColumns()
public void TestFindByDynamicTwoColumns()
{
_db.Users.FindByNameAndPassword("Foo", "secret");
- GeneratedSqlIs("select [dbo].[Users].* from [dbo].[Users] where ([dbo].[Users].[name] = @p1 and [dbo].[Users].[password] = @p2)");
+ GeneratedSqlIs("select " + usersColumns + " from [dbo].[Users] where ([dbo].[Users].[name] = @p1 and [dbo].[Users].[password] = @p2)");
Parameter(0).Is("Foo");
Parameter(1).Is("secret");
}
View
4 Simple.Data.BehaviourTest/NameResolutionTests.cs
@@ -30,7 +30,7 @@ public void NaturalJoinWithIndexersCreatesCorrectCommand()
var orderDate = new DateTime(2010, 1, 1);
_db["Customer"].Find(_db["Customers"]["Orders"]["OrderDate"] == orderDate);
- GeneratedSqlIs("select [dbo].[Customer].* from [dbo].[Customer] join [dbo].[Orders] on ([dbo].[Customer].[CustomerId] = [dbo].[Orders].[CustomerId]) where [dbo].[Orders].[OrderDate] = @p1");
+ GeneratedSqlIs("select [dbo].[Customer].[CustomerId] from [dbo].[Customer] join [dbo].[Orders] on ([dbo].[Customer].[CustomerId] = [dbo].[Orders].[CustomerId]) where [dbo].[Orders].[OrderDate] = @p1");
Parameter(0).Is(orderDate);
}
}
@@ -138,7 +138,7 @@ public void NaturalJoinWithShoutyCaseCreatesCorrectCommand()
{
var orderDate = new DateTime(2010, 1, 1);
_db.Customer.Find(_db.Customers.Orders.OrderDate == orderDate);
- const string expectedSql = "select [dbo].[CUSTOMER].* from [dbo].[CUSTOMER] join [dbo].[ORDER] on " +
+ const string expectedSql = "select [dbo].[CUSTOMER].[CUSTOMER_ID] from [dbo].[CUSTOMER] join [dbo].[ORDER] on " +
"([dbo].[CUSTOMER].[CUSTOMER_ID] = [dbo].[ORDER].[CUSTOMER_ID])"
+ " where [dbo].[ORDER].[ORDER_DATE] = @p1";
View
2  Simple.Data.BehaviourTest/NaturalJoinTest.cs
@@ -29,7 +29,7 @@ public void NaturalJoinCreatesCorrectCommand()
{
var orderDate = new DateTime(2010, 1, 1);
const string expectedSql =
- "select [dbo].[Customer].* from [dbo].[Customer] join [dbo].[Orders] on ([dbo].[Customer].[CustomerId] = [dbo].[Orders].[CustomerId]) where [dbo].[Orders].[OrderDate] = @p1";
+ "select [dbo].[Customer].[CustomerId] from [dbo].[Customer] join [dbo].[Orders] on ([dbo].[Customer].[CustomerId] = [dbo].[Orders].[CustomerId]) where [dbo].[Orders].[OrderDate] = @p1";
_db.Customer.Find(_db.Customer.Orders.OrderDate == orderDate);
GeneratedSqlIs(expectedSql);
View
2  Simple.Data.BehaviourTest/NaturalNamingTest.cs
@@ -25,7 +25,7 @@ protected override void SetSchema(MockSchemaProvider schemaProvider)
public void DotNetNamingIsCorrectlyResolvedInFind()
{
_db.Customers.Find(_db.Customers.CustomerName == "Arthur");
- GeneratedSqlIs("select [dbo].[customers].* from [dbo].[customers] where [dbo].[customers].[customer_name] = @p1");
+ GeneratedSqlIs("select [dbo].[Customers].[CustomerId], [dbo].[Customers].[Customer_Name] from [dbo].[customers] where [dbo].[customers].[customer_name] = @p1");
Parameter(0).Is("Arthur");
}
View
4 Simple.Data.BehaviourTest/Query/FunctionTest.cs
@@ -19,6 +19,8 @@ protected override void SetSchema(MockSchemaProvider schemaProvider)
new[] { "dbo", "Users", "Password" });
}
+ private const string usersColumns = "[dbo].[Users].[Name], [dbo].[Users].[Password]";
+
[Test]
public void SubstringIsEnteredCorrectlyInFindAll()
{
@@ -36,7 +38,7 @@ public void SubstringIsEnteredCorrectlyInFindAll()
[Test]
public void SubstringIsEnteredCorrectlyInFindOne()
{
- const string expected = @"select [dbo].[users].* from [dbo].[users] where substring([dbo].[users].[name],@p1,@p2) = @p3";
+ const string expected = @"select " + usersColumns + " from [dbo].[users] where substring([dbo].[users].[name],@p1,@p2) = @p3";
_db.Users.Find(_db.Users.Name.Substring(0, 1) == "A");
View
17 Simple.Data.BehaviourTest/SchemaQualifiedTableTest.cs
@@ -24,6 +24,7 @@ static Database CreateDatabase(MockDatabase mockDatabase)
return new Database(new AdoAdapter(new MockConnectionProvider(new MockDbConnection(mockDatabase), mockSchemaProvider)));
}
+ private const string usersColumns = "[foo].[users].[id], [foo].[users].[name], [foo].[users].[password], [foo].[users].[age]";
[Test]
public void TestFindEqualWithInt32()
@@ -31,7 +32,7 @@ public void TestFindEqualWithInt32()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.Find(database.foo.Users.Id == 1);
- Assert.AreEqual("select [foo].[users].* from [foo].[users] where [foo].[users].[id] = @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[users] where [foo].[users].[id] = @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual(1, mockDatabase.Parameters[0]);
}
@@ -41,7 +42,7 @@ public void TestFindNotEqualWithInt32()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.Find(database.foo.Users.Id != 1);
- Assert.AreEqual("select [foo].[Users].* from [foo].[Users] where [foo].[Users].[Id] != @p1".ToLowerInvariant().ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[Users] where [foo].[Users].[Id] != @p1".ToLowerInvariant().ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual(1, mockDatabase.Parameters[0]);
}
@@ -51,7 +52,7 @@ public void TestFindGreaterThanWithInt32()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.Find(database.foo.Users.Id > 1);
- Assert.AreEqual("select [foo].[Users].* from [foo].[Users] where [foo].[Users].[Id] > @p1".ToLowerInvariant().ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[Users] where [foo].[Users].[Id] > @p1".ToLowerInvariant().ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual(1, mockDatabase.Parameters[0]);
}
@@ -61,7 +62,7 @@ public void TestFindGreaterThanOrEqualWithInt32()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.Find(database.foo.Users.Id >= 1);
- Assert.AreEqual("select [foo].[Users].* from [foo].[Users] where [foo].[Users].[Id] >= @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[Users] where [foo].[Users].[Id] >= @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual(1, mockDatabase.Parameters[0]);
}
@@ -71,7 +72,7 @@ public void TestFindLessThanWithInt32()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.Find(database.foo.Users.Id < 1);
- Assert.AreEqual("select [foo].[Users].* from [foo].[Users] where [foo].[Users].[Id] < @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[Users] where [foo].[Users].[Id] < @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual(1, mockDatabase.Parameters[0]);
}
@@ -81,7 +82,7 @@ public void TestFindLessThanOrEqualWithInt32()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.Find(database.foo.Users.Id <= 1);
- Assert.AreEqual("select [foo].[Users].* from [foo].[Users] where [foo].[Users].[Id] <= @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[Users] where [foo].[Users].[Id] <= @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual(1, mockDatabase.Parameters[0]);
}
@@ -91,7 +92,7 @@ public void TestFindByDynamicSingleColumn()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.FindByName("Foo");
- Assert.AreEqual("select [foo].[Users].* from [foo].[Users] where [foo].[Users].[name] = @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[Users] where [foo].[Users].[name] = @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual("Foo", mockDatabase.Parameters[0]);
}
@@ -101,7 +102,7 @@ public void TestFindByDynamicTwoColumns()
var mockDatabase = new MockDatabase();
dynamic database = CreateDatabase(mockDatabase);
database.foo.Users.FindByNameAndPassword("Foo", "secret");
- Assert.AreEqual("select [foo].[Users].* from [foo].[Users] where ([foo].[Users].[name] = @p1 and [foo].[Users].[password] = @p2)".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual("select " + usersColumns + " from [foo].[Users] where ([foo].[Users].[name] = @p1 and [foo].[Users].[password] = @p2)".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual("Foo", mockDatabase.Parameters[0]);
Assert.AreEqual("secret", mockDatabase.Parameters[1]);
}
View
6 Simple.Data.BehaviourTest/TransactionTest.cs
@@ -26,6 +26,8 @@ static Database CreateDatabase(MockDatabase mockDatabase)
return new Database(new AdoAdapter(new MockConnectionProvider(new MockDbConnection(mockDatabase), mockSchemaProvider)));
}
+ private const string usersColumns = "[dbo].[Users].[Id], [dbo].[Users].[Name], [dbo].[Users].[Password], [dbo].[Users].[Age]";
+
[Test]
public void TestFindEqualWithInt32()
{
@@ -35,7 +37,7 @@ public void TestFindEqualWithInt32()
{
transaction.Users.Find(database.Users.Id == 1);
}
- Assert.AreEqual("select [dbo].[users].* from [dbo].[users] where [dbo].[users].[id] = @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual(("select " + usersColumns + " from [dbo].[users] where [dbo].[users].[id] = @p1").ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual(1, mockDatabase.Parameters[0]);
}
@@ -48,7 +50,7 @@ public void TestFindByDynamicSingleColumn()
{
transaction.Users.FindByName("Foo");
}
- Assert.AreEqual("select [dbo].[Users].* from [dbo].[Users] where [dbo].[Users].[name] = @p1".ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
+ Assert.AreEqual(("select " + usersColumns + " from [dbo].[Users] where [dbo].[Users].[name] = @p1").ToLowerInvariant(), mockDatabase.Sql.ToLowerInvariant());
Assert.AreEqual("Foo", mockDatabase.Parameters[0]);
}
View
3  Simple.Data.SqlServer/SqlCommandOptimizer.cs
@@ -6,6 +6,7 @@
namespace Simple.Data.SqlServer
{
using System.ComponentModel.Composition;
+ using System.Data.SqlClient;
using System.Text.RegularExpressions;
using Ado;
@@ -14,7 +15,7 @@ public class SqlCommandOptimizer : CommandOptimizer
{
public override System.Data.IDbCommand OptimizeFindOne(System.Data.IDbCommand command)
{
- command.CommandText = Regex.Replace(command.CommandText, "^SELECT ", "SET NOCOUNT ON; SELECT TOP 1 ",
+ command.CommandText = Regex.Replace(command.CommandText, "^SELECT ", "SELECT TOP 1 ",
RegexOptions.IgnoreCase);
return command;
}
View
7 Simple.Data/ActionDisposable.cs
@@ -7,11 +7,16 @@ namespace Simple.Data
{
public class ActionDisposable : IDisposable
{
+ public static readonly IDisposable NoOp = new ActionDisposable();
private readonly Action _action;
+ public ActionDisposable() : this(null)
+ {
+ }
+
public ActionDisposable(Action action)
{
- _action = action;
+ _action = action ?? (() => { });
}
public void Dispose()
View
33 Simple.Data/DynamicTable.cs
@@ -10,13 +10,16 @@
namespace Simple.Data
{
+ using System.Collections;
+
/// <summary>
/// Represents a table in a database, or the nearest equivalent in other data stores.
/// </summary>
public class DynamicTable : DynamicObject
{
- private readonly ConcurrentDictionary<FunctionSignature, Func<object[], object>> _delegates =
- new ConcurrentDictionary<FunctionSignature, Func<object[], object>>();
+ private readonly Dictionary<string, Func<object[], object>> _delegates;
+
+ private readonly ICollection _delegatesAsCollection;
private readonly string _tableName;
private readonly DynamicSchema _schema;
private readonly DataStrategy _dataStrategy;
@@ -39,6 +42,8 @@ internal DynamicTable(string tableName, DataStrategy dataStrategy)
/// <param name="schema">The schema to which the table belongs.</param>
internal DynamicTable(string tableName, DataStrategy dataStrategy, DynamicSchema schema)
{
+ _delegates = new Dictionary<string, Func<object[], object>>();
+ _delegatesAsCollection = _delegates;
_tableName = tableName;
_schema = schema;
_dataStrategy = dataStrategy;
@@ -55,7 +60,27 @@ internal DynamicTable(string tableName, DataStrategy dataStrategy, DynamicSchema
/// </returns>
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
- var func = _delegates.GetOrAdd(FunctionSignature.FromBinder(binder, args), signature => CreateMemberDelegate(signature, binder, args));
+ var signature = FunctionSignature.FromBinder(binder, args);
+ Func<object[], object> func;
+ if (_delegatesAsCollection.IsSynchronized && _delegates.ContainsKey(signature))
+ {
+ func = _delegates[signature];
+ }
+ else
+ {
+ lock (_delegatesAsCollection.SyncRoot)
+ {
+ if (!_delegates.ContainsKey(signature))
+ {
+ func = CreateMemberDelegate(signature, binder, args);
+ _delegates.Add(signature, func);
+ }
+ else
+ {
+ func = _delegates[signature];
+ }
+ }
+ }
if (func != null)
{
result = func(args);
@@ -78,7 +103,7 @@ private static string CreateDelegateName(InvokeMemberBinder binder)
return binder.Name + " " + string.Join(" ", binder.CallInfo.ArgumentNames);
}
- private Func<object[],object> CreateMemberDelegate(FunctionSignature signature, InvokeMemberBinder binder, object[] args)
+ private Func<object[],object> CreateMemberDelegate(string signature, InvokeMemberBinder binder, object[] args)
{
try
{
View
28 Simple.Data/FunctionSignature.cs
@@ -6,10 +6,13 @@
namespace Simple.Data
{
+ using System.Text;
+
internal sealed class FunctionSignature : IEquatable<FunctionSignature>
{
private readonly string _name;
private readonly IList<Parameter> _parameters;
+ private static readonly object obj = new object();
private FunctionSignature(string name, IList<Parameter> parameters)
{
@@ -17,9 +20,30 @@ private FunctionSignature(string name, IList<Parameter> parameters)
_parameters = parameters;
}
- public static FunctionSignature FromBinder(InvokeMemberBinder binder, object[] args)
+ public static string FromBinder(InvokeMemberBinder binder, object[] args)
{
- return new FunctionSignature(binder.Name, GetParameters(binder, args));
+ if (args.Length == 1 && !(args[0] is IList))
+ return string.Format("{0}({1})", binder.Name, (args[0] ?? obj).GetType());
+
+ var builder = new StringBuilder(binder.Name);
+ builder.Append("(");
+ for (int i = 0; i < args.Length; i++)
+ {
+ if (binder.CallInfo.ArgumentNames.Count > i && !string.IsNullOrWhiteSpace(binder.CallInfo.ArgumentNames[i]))
+ {
+ builder.Append(binder.CallInfo.ArgumentNames[i]);
+ builder.Append(":");
+ }
+ var type = (args[i] ?? obj).GetType();
+ builder.Append(type.FullName);
+ var list = args[i] as IList;
+ if (list != null)
+ {
+ builder.AppendFormat("[{0}]", list.Count);
+ }
+ }
+ builder.Append(")");
+ return builder.ToString();
}
private static IList<Parameter> GetParameters(InvokeMemberBinder binder, object[] args)
Please sign in to comment.
Something went wrong with that request. Please try again.