SPRNET-1571 SPRNET-1572 set OracleCommand's BindByName to true

* add native ODP.NET 12 provider
* add managed ODP.NET 12 provider
This commit is contained in:
Marko Lahma
2014-03-14 13:19:59 +02:00
parent 0311d3694d
commit e9ade58ee7
6 changed files with 275 additions and 64 deletions

View File

@@ -8,6 +8,7 @@ Changes (1.3.2 to 2.0)
3. Most of members marked as Obsolete before 2.0 release were removed.
4. DbProvider automatically sets BindByName to true for Oracle's ODP.NET OracleCommand instances when created
Changes (1.3.1 to 1.3.2)
========================

View File

@@ -20,6 +20,7 @@
using System;
using System.Data;
using Spring.Expressions;
using Spring.Reflection.Dynamic;
using Spring.Util;
@@ -32,12 +33,13 @@ namespace Spring.Data.Common
public class DbProvider : IDbProvider
{
private string connectionString;
private IDbMetadata dbMetadata;
private IDynamicConstructor newCommand;
private IDynamicConstructor newConnection;
private IDynamicConstructor newCommandBuilder;
private IDynamicConstructor newDataAdapter;
private IDynamicConstructor newParameter;
private readonly IDbMetadata dbMetadata;
private readonly IDynamicConstructor newCommand;
private readonly IDynamicProperty commandBindByName;
private readonly IDynamicConstructor newConnection;
private readonly IDynamicConstructor newCommandBuilder;
private readonly IDynamicConstructor newDataAdapter;
private readonly IDynamicConstructor newParameter;
/// <summary>
/// Initializes a new instance of the <see cref="DbProvider"/> class.
@@ -47,6 +49,14 @@ namespace Spring.Data.Common
{
this.dbMetadata = dbMetadata;
newCommand = DynamicConstructor.Create(dbMetadata.CommandType.GetConstructor(Type.EmptyTypes));
// Oracle needs custom bind by name property set to true as it's false by default
var bindByNameProperty = dbMetadata.CommandType.GetProperty("BindByName");
if (bindByNameProperty != null && bindByNameProperty.CanWrite)
{
commandBindByName = DynamicProperty.Create(bindByNameProperty);
}
newConnection = DynamicConstructor.Create(dbMetadata.ConnectionType.GetConstructor(Type.EmptyTypes));
newCommandBuilder = DynamicConstructor.Create(dbMetadata.CommandBuilderType.GetConstructor(Type.EmptyTypes));
newDataAdapter = DynamicConstructor.Create(dbMetadata.DataAdapterType.GetConstructor(Type.EmptyTypes));
@@ -60,7 +70,12 @@ namespace Spring.Data.Common
/// <returns>An new <see cref="IDbCommand"/></returns>
public IDbCommand CreateCommand()
{
return newCommand.Invoke(ObjectUtils.EmptyObjects) as IDbCommand;
var command = newCommand.Invoke(ObjectUtils.EmptyObjects) as IDbCommand;
if (command != null && commandBindByName != null)
{
commandBindByName.SetValue(command, dbMetadata.BindByName);
}
return command;
}
/// <summary>
@@ -188,20 +203,16 @@ namespace Spring.Data.Common
/// <returns>The provider specific error code</returns>
public string ExtractError(Exception e)
{
if (!StringUtils.IsNullOrEmpty(dbMetadata.ErrorCodeExceptionExpression))
{
return ExpressionEvaluator.GetValue(e, dbMetadata.ErrorCodeExceptionExpression).ToString();
}
}
else
{
return "Could not extract error code exception type." + e.GetType();
return "Could not extract error code exception type." + e.GetType();
}
}
/// <summary>
/// Determines whether the provided exception is in fact related
/// to database access. This can be provider dependent in .NET 1.1 since
@@ -215,7 +226,6 @@ namespace Spring.Data.Common
/// </returns>
public bool IsDataAccessException(Exception e)
{
if (e is System.Data.Common.DbException)
{
return true;
@@ -225,21 +235,5 @@ namespace Spring.Data.Common
return false;
}
}
/// <summary>
/// Determines whether is data access exception in .NET 1.1 for the specified exception.
/// </summary>
/// <param name="e">The candidate exception.</param>
/// <returns>
/// <c>true</c> if is data access exception in .NET 1.1 for the specified exception; otherwise, <c>false</c>.
/// </returns>
private bool IsDataAccessExceptionBCL11(Exception e)
{
if (e == null)
{
return false;
}
return e.GetType().IsAssignableFrom(DbMetadata.ExceptionType);
}
}
}
}

View File

@@ -500,7 +500,6 @@
</object>
</constructor-arg>
</object>
<object id="OracleODP-11-4.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
@@ -551,11 +550,163 @@
</property>
</object>
</constructor-arg>
</object>
</object>
<object id="OracleODP-12-2.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
<object type="Spring.Data.Common.DbMetadata">
<constructor-arg name="productName" value="Oracle, Oracle provider V2.121.1.0" />
<constructor-arg name="assemblyName" value="Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="connectionType" value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandType" value="Oracle.DataAccess.Client.OracleCommand, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterType" value="Oracle.DataAccess.Client.OracleParameter, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="dataAdapterType" value="Oracle.DataAccess.Client.OracleDataAdapter, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderType" value="Oracle.DataAccess.Client.OracleCommandBuilder, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderDeriveParametersMethod" value="DeriveParameters"/>
<constructor-arg name="parameterDbType" value="Oracle.DataAccess.Client.OracleDbType, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterDbTypeProperty" value="OracleDbType"/>
<constructor-arg name="parameterIsNullableProperty" value="IsNullable"/>
<constructor-arg name="parameterNamePrefix" value=":"/>
<constructor-arg name="exceptionType" value="Oracle.DataAccess.Client.OracleException, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="useParameterNamePrefixInParameterCollection" value="false"/>
<constructor-arg name="useParameterPrefixInSql" value="true"/>
<constructor-arg name="bindByName" value="true"/>
<!-- this is only true for .net 1.1 kept it here just in case we want to revert back to this strategy for
obtaining error codes-->
<constructor-arg name="errorCodeExceptionExpression" value="Number.ToString()"/>
<property name="ErrorCodes.BadSqlGrammarCodes">
<value>900,903,904,917,936,942,17006</value>
</property>
<property name="ErrorCodes.InvalidResultSetAccessCodes">
<value>17003</value>
</property>
<property name="ErrorCodes.DuplicateKeyCodes">
<value>1</value>
</property>
<property name="ErrorCodes.DataAccessResourceFailureCodes">
<value>17002,17447</value>
</property>
<property name="ErrorCodes.DataIntegrityViolationCodes">
<value>1,1400,1722,2291,2292</value>
</property>
<property name="ErrorCodes.CannotAcquireLockCodes">
<value>54</value>
</property>
<property name="ErrorCodes.CannotSerializeTransactionCodes">
<value>8177</value>
</property>
<property name="ErrorCodes.DeadlockLoserCodes">
<value>60</value>
</property>
</object>
</constructor-arg>
</object>
<object id="OracleODP-12-4.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
<object type="Spring.Data.Common.DbMetadata">
<constructor-arg name="productName" value="Oracle, Oracle provider V4.121.1.0" />
<constructor-arg name="assemblyName" value="Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="connectionType" value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandType" value="Oracle.DataAccess.Client.OracleCommand, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterType" value="Oracle.DataAccess.Client.OracleParameter, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="dataAdapterType" value="Oracle.DataAccess.Client.OracleDataAdapter, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderType" value="Oracle.DataAccess.Client.OracleCommandBuilder, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderDeriveParametersMethod" value="DeriveParameters"/>
<constructor-arg name="parameterDbType" value="Oracle.DataAccess.Client.OracleDbType, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterDbTypeProperty" value="OracleDbType"/>
<constructor-arg name="parameterIsNullableProperty" value="IsNullable"/>
<constructor-arg name="parameterNamePrefix" value=":"/>
<constructor-arg name="exceptionType" value="Oracle.DataAccess.Client.OracleException, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="useParameterNamePrefixInParameterCollection" value="false"/>
<constructor-arg name="useParameterPrefixInSql" value="true"/>
<constructor-arg name="bindByName" value="true"/>
<!-- this is only true for .net 1.1 kept it here just in case we want to revert back to this strategy for
obtaining error codes-->
<constructor-arg name="errorCodeExceptionExpression" value="Number.ToString()"/>
<property name="ErrorCodes.BadSqlGrammarCodes">
<value>900,903,904,917,936,942,17006</value>
</property>
<property name="ErrorCodes.InvalidResultSetAccessCodes">
<value>17003</value>
</property>
<property name="ErrorCodes.DuplicateKeyCodes">
<value>1</value>
</property>
<property name="ErrorCodes.DataAccessResourceFailureCodes">
<value>17002,17447</value>
</property>
<property name="ErrorCodes.DataIntegrityViolationCodes">
<value>1,1400,1722,2291,2292</value>
</property>
<property name="ErrorCodes.CannotAcquireLockCodes">
<value>54</value>
</property>
<property name="ErrorCodes.CannotSerializeTransactionCodes">
<value>8177</value>
</property>
<property name="ErrorCodes.DeadlockLoserCodes">
<value>60</value>
</property>
</object>
</constructor-arg>
</object>
<object id="OracleODP-Managed-12-4.0" type="Spring.Data.Common.DbProvider, Spring.Data" singleton="false">
<constructor-arg name="dbMetaData">
<object type="Spring.Data.Common.DbMetadata">
<constructor-arg name="productName" value="Oracle, Oracle Managed provider V4.121.1.0" />
<constructor-arg name="assemblyName" value="Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="connectionType" value="Oracle.ManagedDataAccess.Client.OracleConnection, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandType" value="Oracle.ManagedDataAccess.Client.OracleCommand, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterType" value="Oracle.ManagedDataAccess.Client.OracleParameter, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="dataAdapterType" value="Oracle.ManagedDataAccess.Client.OracleDataAdapter, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderType" value="Oracle.ManagedDataAccess.Client.OracleCommandBuilder, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="commandBuilderDeriveParametersMethod" value="DeriveParameters"/>
<constructor-arg name="parameterDbType" value="Oracle.ManagedDataAccess.Client.OracleDbType, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="parameterDbTypeProperty" value="OracleDbType"/>
<constructor-arg name="parameterIsNullableProperty" value="IsNullable"/>
<constructor-arg name="parameterNamePrefix" value=":"/>
<constructor-arg name="exceptionType" value="Oracle.ManagedDataAccess.Client.OracleException, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<constructor-arg name="useParameterNamePrefixInParameterCollection" value="false"/>
<constructor-arg name="useParameterPrefixInSql" value="true"/>
<constructor-arg name="bindByName" value="true"/>
<!-- this is only true for .net 1.1 kept it here just in case we want to revert back to this strategy for
obtaining error codes-->
<constructor-arg name="errorCodeExceptionExpression" value="Number.ToString()"/>
<property name="ErrorCodes.BadSqlGrammarCodes">
<value>900,903,904,917,936,942,17006</value>
</property>
<property name="ErrorCodes.InvalidResultSetAccessCodes">
<value>17003</value>
</property>
<property name="ErrorCodes.DuplicateKeyCodes">
<value>1</value>
</property>
<property name="ErrorCodes.DataAccessResourceFailureCodes">
<value>17002,17447</value>
</property>
<property name="ErrorCodes.DataIntegrityViolationCodes">
<value>1,1400,1722,2291,2292</value>
</property>
<property name="ErrorCodes.CannotAcquireLockCodes">
<value>54</value>
</property>
<property name="ErrorCodes.CannotSerializeTransactionCodes">
<value>8177</value>
</property>
<property name="ErrorCodes.DeadlockLoserCodes">
<value>60</value>
</property>
</object>
</constructor-arg>
</object>
<!-- My Sql -->
<!-- Connector/NET 1.0 -->

View File

@@ -23,7 +23,9 @@ using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Threading;
using NUnit.Framework;
using Spring.Context;
using Spring.Context.Support;
using Spring.Threading;
@@ -41,7 +43,7 @@ namespace Spring.Data.Common
public class AsyncTestDbProviderFactory : AsyncTestTask
{
private string providerName;
private readonly string providerName;
public AsyncTestDbProviderFactory(int iterations, string providerName)
: base(iterations)
@@ -66,12 +68,12 @@ namespace Spring.Data.Common
//Other tests in this assembly will have already initialized the internal context that is part of DbProviderFactory
//Reset it back to null so that tests for specifiying additional database providers will be able 're-initialize'
//the internal Context of DbProviderFactory.
//Spring.Objects.Factory.Xml.NamespaceParserRegistry.RegisterParser(typeof(Spring.Data.Config.DatabaseNamespaceParser));
//Spring.Objects.Factory.Xml.NamespaceParserRegistry.RegisterParser(typeof(Spring.Data.Config.DatabaseNamespaceParser));
if (DbProviderFactory.ApplicationContext != null)
{
FieldInfo fieldInfo = typeof (DbProviderFactory).GetField("ctx", BindingFlags.NonPublic | BindingFlags.Static);
fieldInfo.SetValue(null, null);
}
FieldInfo fieldInfo = typeof (DbProviderFactory).GetField("ctx", BindingFlags.NonPublic | BindingFlags.Static);
fieldInfo.SetValue(null, null);
}
ctx = new XmlApplicationContext("assembly://Spring.Data.Tests/Spring.Data.Common/DbProviderFactoryTests.xml");
}
@@ -82,17 +84,16 @@ namespace Spring.Data.Common
AsyncTestTask t2 = new AsyncTestDbProviderFactory(1000, "SqlServer-2.0").Start();
AsyncTestTask t3 = new AsyncTestDbProviderFactory(1000, "SqlServer-2.0").Start();
AsyncTestTask t4 = new AsyncTestDbProviderFactory(1000, "SqlServer-2.0").Start();
t1.AssertNoException();
t2.AssertNoException();
t3.AssertNoException();
t4.AssertNoException();
}
[Test]
public void AdditionalResourceName()
{
{
IDbProvider provider = DbProviderFactory.GetDbProvider("Test-SqlServer-2.0");
Assert.IsNotNull(provider);
}
@@ -100,11 +101,10 @@ namespace Spring.Data.Common
[Test]
public void BadErrorExpression()
{
IDbProvider provider = DbProviderFactory.GetDbProvider("Test-SqlServer-2.0-BadErrorCodeExpression");
Assert.IsNotNull(provider);
string errorCode = provider.ExtractError(new Exception("foo"));
Assert.AreEqual("156",errorCode);
Assert.AreEqual("156", errorCode);
}
[Test]
@@ -126,8 +126,7 @@ namespace Spring.Data.Common
Assert.IsNotNull(provider.CreateParameter());
Assert.AreEqual("@Foo", provider.CreateParameterName("Foo"));
}
[Test]
public void DefaultInstanceWithOleDb20()
{
@@ -140,7 +139,7 @@ namespace Spring.Data.Common
Assert.IsNotNull(provider.CreateParameter());
Assert.AreEqual("?", provider.CreateParameterName("Foo"));
}
[Test]
public void DefaultInstanceWithMicrsoftOracleClient20()
{
@@ -155,7 +154,7 @@ namespace Spring.Data.Common
}
#if NET_4_0
[Test]
public void DefaultInstanceWithSqlServer40()
{
@@ -184,19 +183,82 @@ namespace Spring.Data.Common
}
#endif
//[Test]
//Comment in for specific testing with oracle as can't put oracle client in public code repository
public void DefaultInstanceWithOracleClient20()
[Test]
public void DefaultInstanceWithOracleClient10_20()
{
IDbProvider provider = DbProviderFactory.GetDbProvider("OracleODP-2.0");
Assert.AreEqual("Oracle, Oracle provider V2.102.2.20", provider.DbMetadata.ProductName);
Assert.IsNotNull(provider.CreateCommand());
if (Type.GetType("Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342") == null)
{
Assert.Inconclusive("oracle data access libs not found, skipping test");
}
AssertOracleProvider("OracleODP-2.0", "Oracle, Oracle provider V2.102.2.20");
}
[Test]
public void DefaultInstanceWithOracleClient11_20()
{
if (Type.GetType("Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342") == null)
{
Assert.Inconclusive("oracle data access libs not found, skipping test");
}
AssertOracleProvider("OracleODP-11-2.0", "Oracle, Oracle provider V2.112.3.0");
}
[Test]
public void DefaultInstanceWithOracleClient12_20()
{
if (Type.GetType("Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342") == null)
{
Assert.Inconclusive("oracle data access libs not found, skipping test");
}
AssertOracleProvider("OracleODP-12-2.0", "Oracle, Oracle provider V2.121.1.0");
}
[Test]
public void DefaultInstanceWithOracleClient12_40()
{
if (Type.GetType("Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342") == null)
{
Assert.Inconclusive("oracle data access libs not found, skipping test");
}
AssertOracleProvider("OracleODP-12-4.0", "Oracle, Oracle provider V4.121.1.0");
}
[Test]
public void DefaultInstanceWithOracleManagedClient11_40()
{
if (Type.GetType("Oracle.ManagedDataAccess.Client.OracleConnection, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342") == null)
{
Assert.Inconclusive("oracle data access libs not found, skipping test");
}
AssertOracleProvider("OracleODP-Managed-12-4.0", "Oracle, Oracle Managed provider V4.121.1.0");
}
private static void AssertOracleProvider(string providerName, string productName)
{
IDbProvider provider = DbProviderFactory.GetDbProvider(providerName);
Assert.AreEqual(productName, provider.DbMetadata.ProductName);
var command = provider.CreateCommand();
Assert.IsNotNull(command);
// check if parameter has readable BindByName property
var property = command.GetType().GetProperty("BindByName");
if (property != null)
{
var bindByNameValue = property.GetValue(command, null);
Assert.That(bindByNameValue, Is.EqualTo(provider.DbMetadata.BindByName), "BindByName had wrong value");
}
Assert.IsNotNull(provider.CreateCommandBuilder());
Assert.IsNotNull(provider.CreateConnection());
Assert.IsNotNull(provider.CreateDataAdapter());
Assert.IsNotNull(provider.CreateParameter());
Assert.AreEqual(":Foo", provider.CreateParameterName("Foo"));
Assert.AreEqual(":Foo", provider.CreateParameterName("Foo"));
}
/*
@@ -218,22 +280,21 @@ namespace Spring.Data.Common
//Initialize internal application context. factory
DbProviderFactory.GetDbProvider("SqlServer-2.0");
IApplicationContext ctx = DbProviderFactory.ApplicationContext;
IList<string> dbProviderNames = ctx.GetObjectNamesForType(typeof(IDbProvider));
Assert.IsTrue(dbProviderNames.Count > 0);
IList<string> dbProviderNames = ctx.GetObjectNamesForType(typeof (IDbProvider));
Assert.IsTrue(dbProviderNames.Count > 0);
}
private void AssertIsSqlServer2005(IDbProvider provider)
{
Assert.AreEqual("Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0",
provider.DbMetadata.ProductName);
provider.DbMetadata.ProductName);
AssertCommonSqlServerErrorCodes(provider);
}
private void AssertIsSqlServer40(IDbProvider provider)
{
Assert.AreEqual("Microsoft SQL Server, provider V4.0.0.0 in framework .NET V4.0",
provider.DbMetadata.ProductName);
provider.DbMetadata.ProductName);
AssertCommonSqlServerErrorCodes(provider);
}
@@ -248,4 +309,4 @@ namespace Spring.Data.Common
Assert.IsFalse(Array.IndexOf(codes.BadSqlGrammarCodes, "1xx56") >= 0);
}
}
}
}

View File

@@ -84,6 +84,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Oracle.ManagedDataAccess">
<HintPath>..\..\..\packages\odp.net.managed.121.1.1\lib\net40\Oracle.ManagedDataAccess.dll</HintPath>
</Reference>
<Reference Include="Rhino.Mocks, Version=2.9.6.40380, Culture=neutral, PublicKeyToken=0b3305902db7183f">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\Rhino.Mocks.dll</HintPath>

View File

@@ -2,4 +2,5 @@
<packages>
<package id="Common.Logging" version="2.1.2" targetFramework="net40" />
<package id="NUnit" version="2.6.3" targetFramework="net40" />
<package id="odp.net.managed" version="121.1.1" targetFramework="net40" />
</packages>