我知道这是一个老问题,但我最近需要使用log4net将CLOB参数传递给程序包过程。我无法使用我在网上找到的建议做到这一点,其中包括将DbType设置为字符串和删除大小的建议。
我正在使用一个采用CLOB类型参数的Oracle程序包过程。使用自定义的AdoNetAppenderParameter,我可以将长字符串(270k +字符)传递给过程并将它们存储在数据库(Oracle 9i)中。首先,我不得不使用Oracle的数据访问提供程序(毕竟,微软的System.Data.OracleClient已被deprecated)。您的项目必须引用Oracle.DataAccess.dll。我通过在NuGet包管理器中搜索“oracle.dataaccess”来获得NuGet包。
该库具有DbParameter实现,OracleParameter,它具有OracleDbType属性。该属性的类型为OracleDbType,这是一个枚举,其值为Clob。
添加引用之后,我改变了附加器的连接类型:
<connectionType value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
然后,我创建,创建一个新的OracleParameter并设置其类型为CLOB自定义AdoNetAppenderParameter:
public class OracleAdoNetAppenderParameter : AdoNetAppenderParameter
{
public OracleDbType OracleDbType { get; set; }
public override void Prepare(System.Data.IDbCommand command)
{
if (!(command is OracleCommand))
{
string message = string.Format("The log4net parameter of type {0} can only be used with an appender connection of type {1}. The expected command type, {2}, cannot be supplied. Please check the parent appender's connectionType property.",
this.GetType(), typeof(OracleConnection), typeof(OracleCommand));
throw new System.ArgumentException(message, "command");
}
var parameter = command.CreateParameter() as OracleParameter;
parameter.ParameterName = base.ParameterName;
parameter.OracleDbType = this.OracleDbType;
command.Parameters.Add(parameter);
}
}
我暴露了一个属性OracleDbType,所以我可以通过配置来指定它。
我最初没有公开该属性,将该属性命名为OracleClobAdoNetAppenderParameter,并将Prepared方法中的OracleDbType属性设置为Clob。
我创建的类之后,我加入了参数的附加目的地的配置,这样的:
<parameter type="YourNamespace.OracleAdoNetAppenderParameter, YourAssembly">
<OracleDbType value="Clob" />
<parameterName value=":yourProcedureClobParam"/>
<layout type="..."></layout>
</parameter>
您可以使用自己的布局。我通过log4net的上下文将自己的大字符串作为自定义参数传递。
下面是我使用的最终配置:
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<connectionType value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<connectionString value="data source=xxx;User ID=xxx;Password=xxx"/>
<commandText value="MY_PKG.LogMessage"/>
<commandType value="StoredProcedure" />
<!-- SERVICE_MESSAGE -->
<parameter type="MyNamespace.OracleAdoNetAppenderParameter, MyAssembly">
<OracleDbType value="Clob" />
<parameterName value=":service_message"/>
<layout type="log4net.Layout.RawPropertyLayout">
<key value="service_message"/>
</layout>
</parameter>
<!-- LOG_LEVEL -->
<parameter>
<parameterName value=":type"/>
<dbType value="String"/>
<size value="20"/>
<layout type="log4net.Layout.PatternLayout" value="%level"/>
</parameter>
<!-- LOG_DATE -->
<parameter>
<parameterName value=":timestamp"/>
<dbType value="DateTime"/>
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<!-- MESSAGE -->
<parameter>
<parameterName value=":message"/>
<dbType value="String"/>
<size value="1000"/>
<layout type="log4net.Layout.PatternLayout" value="%message"/>
</parameter>
<!-- EXCEPTION -->
<parameter>
<parameterName value=":error"/>
<dbType value="String"/>
<size value="4000"/>
<layout type="log4net.Layout.ExceptionLayout"/>
</parameter>
......
</appender>
希望它能帮助。