/// <summary> /// Get the schema information for this store. /// </summary> /// <returns>The schema information</returns> /// <remarks> /// If it has already been retrieved for this store, then just /// return that copy. If it hasn't been retrieved, then grab /// it from the AppDomain-wide cache or from the database. /// </remarks> internal LearningStoreSchema GetSchema() { // If the information isn't available, then call the static // method to cache schema information if (m_schema == null) { m_schema = GetSchemaInformationFromCache(m_connectionString, m_impersonationBehavior, m_debugLog); } // Return it return(m_schema); }
/// <summary> /// Create a new instance of the <Typ>LearningStoreQuery</Typ> class /// </summary> /// <returns>A new <Typ>LearningStoreQuery</Typ></returns> /// <param name="viewName">Name of the view for the query. If this is an item type name, /// then the default view for the item type is used.</param> /// <exception cref="ArgumentNullException"><paramref name="viewName"/> is a null reference.</exception> /// <exception cref="InvalidOperationException">The store was created /// by a different version of this product, the schema information stored /// inside the database is invalid, or <paramref name="viewName"/> /// does not refer to a view or item type in the store.</exception> /// <exception cref="SqlException">The database could not be /// opened or other SQL error.</exception> /// <remarks> /// See the <Typ>LearningStoreQuery</Typ> documentation for more information /// about constructing queries. /// </remarks> /// <example>The following code opens a store and creates a new query: /// <code language="C#"> /// LearningStore store = new LearningStore("Server=Learning;Database=Mls;Integrated Security=true", "Bob"); /// LearningStoreQuery query = store.CreateQuery("AttemptItem"); /// </code> /// </example> public LearningStoreQuery CreateQuery(string viewName) { // Check parameters if (viewName == null) { throw new ArgumentNullException("viewName"); } // Get the information about the item LearningStoreSchema schema = GetSchema(); LearningStoreView view = null; if (!schema.TryGetViewByName(viewName, out view)) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, LearningStoreStrings.ViewNotFoundInSchema, viewName)); } return(new LearningStoreQuery(this, view, m_locale)); }
/// <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; } }