#.net #database #oracle #.net-core #f#
Вопрос:
У меня есть некоторый код, написанный на F#, с использованием .NET Core и ASP.NET Ядро. Предполагается, что он регистрирует прослушиватели изменений в базе данных, и время от времени он работает:
namespace Raptor.ChangeListener.Oracle open System open System.Data open Microsoft.Extensions.Logging open Microsoft.Extensions.Options open Oracle.ManagedDataAccess.Client open Raptor.ChangeListener [lt;Sealedgt;] type OracleChangeListenerOptions() = member val ConnectionString = Unchecked.defaultoflt;stringgt; with get, set member val Query = Unchecked.defaultoflt;stringgt; with get, set member val Timeout = Unchecked.defaultoflt;TimeSpangt; with get, set type OracleChangeListener(options: OracleChangeListenerOptions IOptions, logger: ILoggerlt;OracleChangeListenergt;) = let options = options.Value let mutable disposed = false let sync = obj() let mutable handlers: (Guid * Action) list = [] let mutable connection: OracleConnection = null let mutable command : OracleCommand = null let mutable dependency: OracleDependency = null let startup = async { connection lt;- new OracleConnection(options.ConnectionString) connection.StateChange.Add(fun state -gt; if not disposed then match state.CurrentState with | ConnectionState.Broken -gt; logger.LogError(sprintf "Connection Broken: %s" options.Query) | ConnectionState.Closed -gt; logger.LogError(sprintf "Connection Closed: %s" options.Query) | _ -gt; () ) do! connection.OpenAsync() |gt; Async.AwaitTask command lt;- new OracleCommand(options.Query, connection) dependency lt;- new OracleDependency(command) // these don't exist without first setting the dependency command.Notification.IsNotifiedOnce lt;- false command.Notification.Timeout lt;- int64 options.Timeout.TotalSeconds let test = (command, dependency) dependency.OnChange.Add(fun state -gt; if not disposed then try logger.LogInformation( let info = state.Info.ToString() let typ = state.Type.ToString() sprintf "%s Notification Change Type: %s, TableName: %A" info typ state.ResourceNames ) for _, handler in handlers do try handler.Invoke() with ex -gt; logger.LogError(ex, "OracleChangeListener handler error") with ex -gt; logger.LogError(ex, "OracleChangeListener error") ) match command.ExecuteNonQuery() with | -1 -gt; () | n -gt; failwithf "Error Code In Listener: %i" n } |gt; Async.StartAsTask interface IChangeListener with member _.AddHandler handler = lock sync (fun () -gt; let key = Guid.NewGuid() handlers lt;- List.append handlers [(key, handler)] key ) member _.RemoveHandler key = lock sync (fun () -gt; handlers lt;- handlers |gt; List.where (fun (k, _) -gt; k lt;gt; key) ) interface IDisposable with member this.Dispose() = if not disposed then disposed lt;- true // flag early for internal checks if not (isNull dependency) then dependency.RemoveRegistration(connection) if not (isNull command ) then command .Dispose() if not (isNull connection) then connection.Dispose() GC.SuppressFinalize(this) [lt;Sealedgt;] type OracleChangeListenerlt;'TCategorygt;(options, logger) = inherit OracleChangeListener(options, logger) interface IChangeListenerlt;'TCategorygt;
когда я выбираю из DBA_CHANGE_NOTIFICATION_REGS
базы данных, я вижу все необходимые регистрации на месте:
Но чаще всего, и я не могу определить, в чем причина этого, регистрации производятся с портом -1 вместо действительного номера порта, например так:
Когда это происходит, ни одна из служб не получает надлежащего уведомления об изменении зарегистрированных таблиц. Кроме того, все недопустимые строки удаляются при изменении, которое должно вызвать уведомление.