sqlcontext.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SqlContext.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">Microsoft</owner>
  6. // <owner current="true" primary="false">Microsoft</owner>
  7. // <owner current="true" primary="false">daltodov</owner>
  8. //------------------------------------------------------------------------------
  9. namespace Microsoft.SqlServer.Server {
  10. using System;
  11. using System.Data.Common;
  12. using System.Data.SqlClient;
  13. using System.Data.SqlTypes;
  14. using System.Diagnostics;
  15. using System.Security.Principal;
  16. public sealed class SqlContext {
  17. // There are no publicly visible instance methods/properties on SqlContext.
  18. // With the current design, the user should never get an actual instance of
  19. // this class. Instances are only used internally to hold owned objects
  20. // such as SqlPipe and SqlTriggerContext.
  21. private SmiContext _smiContext;
  22. private SqlPipe _pipe;
  23. private SqlTriggerContext _triggerContext;
  24. private SqlContext( SmiContext smiContext ) {
  25. _smiContext = smiContext;
  26. _smiContext.OutOfScope += new EventHandler(OnOutOfScope);
  27. }
  28. //
  29. // Public API
  30. //
  31. public static bool IsAvailable {
  32. get {
  33. bool result = InOutOfProcHelper.InProc;
  34. return result;
  35. }
  36. }
  37. // Get the SqlPipe (if any) for the current scope.
  38. public static SqlPipe Pipe {
  39. get {
  40. return CurrentContext.InstancePipe;
  41. }
  42. }
  43. // Get the SqlTriggerContext (if any) for the current scope.
  44. public static SqlTriggerContext TriggerContext {
  45. get {
  46. return CurrentContext.InstanceTriggerContext;
  47. }
  48. }
  49. public static WindowsIdentity WindowsIdentity{
  50. get {
  51. return CurrentContext.InstanceWindowsIdentity;
  52. }
  53. }
  54. //
  55. // Internal class methods
  56. //
  57. // CurrentContext should be the *only* way to get to an instance of SqlContext.
  58. private static SqlContext CurrentContext {
  59. get {
  60. SmiContext smiContext = SmiContextFactory.Instance.GetCurrentContext();
  61. SqlContext result = (SqlContext)smiContext.GetContextValue( (int)SmiContextFactory.ContextKey.SqlContext );
  62. if ( null == result ) {
  63. result = new SqlContext( smiContext );
  64. smiContext.SetContextValue( (int)SmiContextFactory.ContextKey.SqlContext, result );
  65. }
  66. return result;
  67. }
  68. }
  69. //
  70. // Internal instance methods
  71. //
  72. private SqlPipe InstancePipe {
  73. get {
  74. if ( null == _pipe && _smiContext.HasContextPipe ) {
  75. _pipe = new SqlPipe( _smiContext );
  76. }
  77. Debug.Assert( null == _pipe || _smiContext.HasContextPipe, "Caching logic error for contained pipe!" );
  78. return _pipe;
  79. }
  80. }
  81. private SqlTriggerContext InstanceTriggerContext {
  82. get {
  83. if ( null == _triggerContext ) {
  84. bool[] columnsUpdated;
  85. TriggerAction triggerAction;
  86. SqlXml eventInstanceData;
  87. SmiEventSink_Default eventSink = new SmiEventSink_Default();
  88. _smiContext.GetTriggerInfo(eventSink, out columnsUpdated, out triggerAction, out eventInstanceData);
  89. eventSink.ProcessMessagesAndThrow();
  90. if (TriggerAction.Invalid != triggerAction) {
  91. _triggerContext = new SqlTriggerContext( triggerAction, columnsUpdated, eventInstanceData );
  92. }
  93. }
  94. return _triggerContext;
  95. }
  96. }
  97. private WindowsIdentity InstanceWindowsIdentity {
  98. get {
  99. return _smiContext.WindowsIdentity;
  100. }
  101. }
  102. // Called whenever the context goes out of scope, we need to make
  103. // sure that we release internal state, such as the pipe's record buffer
  104. private void OnOutOfScope( object s, EventArgs e ) {
  105. if (Bid.AdvancedOn) {
  106. Bid.Trace( "<sc.SqlContext.OutOfScope|ADV> SqlContext is out of scope\n" );
  107. }
  108. if ( null != _pipe ) {
  109. _pipe.OnOutOfScope();
  110. }
  111. _triggerContext = null;
  112. }
  113. }
  114. }