/// <summary> /// Create a LearningStoreXml from some data within a row of a /// LogableSqlCommand /// </summary> /// <param name="command">The LogableSqlCommand. The current position is /// not modified.</param> /// <param name="startingColumn">The index of the first column to be /// examined. On exit, this index contains the last column examined /// plus one.</param> /// <returns>The <Typ>LearningStoreXml</Typ>, or null if a /// value is not found.</returns> /// <remarks>Only examines one column. Assumes that the column contains /// an XML value. If the column is non-null, a LearningStoreXml /// is returned. If the column is null, null is returned. /// </remarks> private static LearningStoreXml ReadXmlColumns(LogableSqlCommand command, ref int startingColumn) { if (command.IsDBNull(startingColumn)) { startingColumn++; return(null); } else { SqlXml xml = command.GetSqlXml(startingColumn); startingColumn++; return(new LearningStoreXml(xml)); } }
/// <summary> /// Get the schema information for this store from the cache or from the database. /// </summary> /// <param name="connectionString">Connection string used to access the store.</param> /// <param name="impersonationBehavior">Identifies which <c>WindowsIdentity</c> is used to /// access the database when impersonation is involved.</param> /// <param name="debugLog">Location to which the debug log should be written, or /// null if there isn't a debug log.</param> /// <returns>The schema information.</returns> private static LearningStoreSchema GetSchemaInformationFromCache(string connectionString, ImpersonationBehavior impersonationBehavior, TextWriter debugLog) { // Try to find the connection in the cache lock (s_allSchemasLock) { LearningStoreSchema schema; if (s_allSchemas.TryGetValue(connectionString, out schema)) { return(schema); } } // Not found in the cache -- so go get it from the database // This try/catch block is here for security reasons. Search MSDN for // "WrapVulnerableFinallyClausesInOuterTry" to see details. try { WindowsImpersonationContext impersonationContext = null; try { // Impersonate if necessary if (impersonationBehavior == ImpersonationBehavior.UseOriginalIdentity) { // Not adding it to the disposer, since that could fail (e.g., OutOfMemoryException), // which could cause a security hole. Instead, we'll clean it up manually later. impersonationContext = WindowsIdentity.Impersonate(IntPtr.Zero); } using (Microsoft.LearningComponents.Disposer disposer = new Microsoft.LearningComponents.Disposer()) { // Create a connection SqlConnection connection = new SqlConnection(connectionString); disposer.Push(connection); connection.Open(); // Create a command to retrieve information from the configuration table LogableSqlCommand command = new LogableSqlCommand(connection, debugLog); disposer.Push(command); // Execute command.Execute( "SELECT EngineVersion,\r\n" + " SchemaDefinition\r\n" + "FROM Configuration\r\n"); // Read return values from the database if (!command.Read()) { throw new LearningComponentsInternalException("LSTR1500"); } if (command.GetFieldCount() != 2) { throw new LearningComponentsInternalException("LSTR1510"); } int engineVersion = command.GetInt32(0); SqlXml schemaXml = command.GetSqlXml(1); XPathDocument schemaDoc; using (XmlReader reader = schemaXml.CreateReader()) { schemaDoc = new XPathDocument(reader); } LearningStoreSchema newSchema = LearningStoreSchema.CreateSchema(schemaDoc); if (command.Read()) { throw new LearningComponentsInternalException("LSTR1520"); } if (command.NextResult()) { throw new LearningComponentsInternalException("LSTR1530"); } // Fail if a different engine created this if (engineVersion != LearningStore.EngineVersion) { throw new InvalidOperationException(LearningStoreStrings.IncompatibleEngineVersion); } // Save it in the cache lock (s_allSchemasLock) { LearningStoreSchema schema; if (s_allSchemas.TryGetValue(connectionString, out schema)) { return(schema); } s_allSchemas.Add(connectionString, newSchema); } return(newSchema); } } finally { if (impersonationContext != null) { impersonationContext.Dispose(); } } } catch { throw; } }