Current filter:
                                You should refresh the page.
                                  •  Hi,

                                    I'd like to use the class "DbDocumentStorage" to storage my report cache pages in DataBase when i execute a reports (xtrareports).
                                    I registered this class according the code below:
                                    However, i din't see any tables created in my DataBase.

                                    This approach works to Oracle and Sqlserver?


                                    This code is correct?I'm using .Net core.

                                          var exportedDocumentService = new ExportedDocumentService(Path.Combine(env.ContentRootPath, "/ExportedDocuments/"), "http://localhost:7017/DXXRDV/GetExportResult");

                                          //Using storage File.
                                          /*services.AddSingleton<ICachedReportSourceWebResolver, CustomCachedReportSourceWebResolver>();
                                          services.ConfigureReportingServices(configurator => {
                                            configurator.ConfigureWebDocumentViewer(viewerConfigurator => {
                                              viewerConfigurator.UseFileDocumentStorage(System.IO.Path.Combine("c:\temp\cachedevex", "DocumentStorage"), StorageSynchronizationMode.InterProcess);

                                          //In this example, i need to use DataBase Storage Document.
                                          var storage = new DbDocumentStorage("Data Source=localhost; database=TRFDb_New; Integrated Security=True; TrustServerCertificate=True; Connection Timeout=30;");

                                          //The short-time cache
                                          var shortdueTime = TimeSpan.FromSeconds(10);
                                          var shortperiod = TimeSpan.FromSeconds(10);
                                          var shortreportTimeTolive = TimeSpan.FromSeconds(10);
                                          var shortdocumentTimeToLive = TimeSpan.FromSeconds(10);
                                            new CacheCleanerSettings(shortdueTime, shortperiod, shortreportTimeTolive, shortdocumentTimeToLive));

                                          //The long-time cache
                                          var longdueTime = TimeSpan.FromSeconds(30);
                                          var longperiod = TimeSpan.FromSeconds(30);
                                          var longreportTimeTolive = TimeSpan.FromSeconds(30);
                                          var longdocumentTimeToLive = TimeSpan.FromSeconds(30);
                                          var longexportedDocumentTimeToLive = TimeSpan.FromSeconds(30);
                                          services.AddSingleton<StorageCleanerSettings>(new StorageCleanerSettings(longdueTime,
                                            longperiod, longreportTimeTolive, longdocumentTimeToLive, longexportedDocumentTimeToLive));

                                          return services;

                                1 Solution

                                Creation Date Importance Sort by

                                Important Note: The approach provided below does not fully support multi-server (Web Farm) environments because access to the database is not synchronized between multiple instances.


                                To run the Document Viewer control with the DbDocumentStorage enabled, it is necessary to use the Bind(String) method to open reports by unique names. Create an ICachedReportSourceWebResolver service that will return reports wrapped by the CachedReportSourceWeb component by the names passed to the  OpenReport(String) method:

                                public class CustomCachedReportSourceWebResolver : ICachedReportSourceWebResolver { string connectionString; public CustomCachedReportSourceWebResolver(IConfiguration configuration) { connectionString = ConfigurationExtensions.GetConnectionString(configuration, "DefaultConnection"); ; } public bool TryGetCachedReportSourceWeb(string reportEntry, out CachedReportSourceWeb CachedReportSourceWeb) { ... CachedReportSourceWeb = new CachedReportSourceWeb(new YourReportClass()); return true; } }

                                Then it is necessary to create and register the IDocumentStorageProvider service that will manage creating DbDocumentStorage for each report opened in the viewer control. The DbDocumentStorage class stores a report's documents and metadata in a "Documents" table that is automatically created in a database specified by the connection string that is passed to the DbDocumentStorage class's constructor. Also this constructor receives a documentId parameter that is used as a primary key for the documents stored in this table. Each previewed document has its own unique documentId. Note that the documents data is saved to database automatically. At the same time, these records are not cleared from the database, so the IDocumentStorageProvider service should also provide the expired document clearing logic. For example, you can create an additional table in your database (e.g., "DocumentsAccessDate") that will store the last access time for each document. This way, it will be possible to clear all expired documents from the database when the Clear method is called. For example, use the following code to implement the IDocumentStorageProvider service:

                                public class CustomDocumentStorageProvider : IDocumentStorageProvider { string connectionString; public CustomDocumentStorageProvider(IConfiguration configuration) { connectionString = ConfigurationExtensions.GetConnectionString(configuration, "DefaultConnection"); ; } public void Clear(TimeSpan timeToLive) { List<string> documentsToDelete = new List<string>(); using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); //Collect all expired documents SqlDataReader reader = new SqlCommand($"SELECT [DocumentId] FROM [DocumentsAccessDate] WHERE DATEDIFF(s,[LastAccessDate], getdate()) > {timeToLive.TotalSeconds}", connection).ExecuteReader(); while (reader.Read()) { documentsToDelete.Add($"'{reader[0]}'"); } reader.Close(); } if (documentsToDelete.Count > 0) { //Delete expired documents Execute($"DELETE FROM [Documents] WHERE [DocumentId] IN ({String.Join(",", documentsToDelete)})"); Execute($"DELETE FROM [DocumentsAccessDate] WHERE [DocumentId] IN ({String.Join(",", documentsToDelete)})"); } } public DocumentStorage CreateNew(string id) { //Create AccessDate record Execute($"INSERT INTO [DocumentsAccessDate] ([DocumentId], [LastAccessDate]) VALUES ('{id}', '{DateTime.Now}')"); return new DbDocumentStorage(connectionString, id); } public bool TryGet(string id, out DocumentStorage documentStorage) { try { //If Document exists if ((int)Execute($"SELECT COUNT ([DocumentId]) FROM [Documents] WHERE [DocumentId] = '{id}'", SqlExecutionType.Scalar) >= 1) { //Update AccessDate Execute($"UPDATE [DocumentsAccessDate] SET [LastAccessDate] = '{DateTime.Now}' WHERE [DocumentId] = '{id}'"); documentStorage = new DbDocumentStorage(connectionString, id); return true; } } catch(Exception ex) { } documentStorage = null; return false; } protected object Execute(string query, SqlExecutionType executionType = SqlExecutionType.NonQuery) { using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand(query, connection); switch(executionType) { case SqlExecutionType.NonQuery: return command.ExecuteNonQuery(); case SqlExecutionType.Scalar: return command.ExecuteScalar(); } return null; } } } public enum SqlExecutionType { NonQuery, Scalar };

                                Finally, if you are going to use the  content editing functionality in an exported document, it is necessary to call the viewerConfigurator.UseFileExportedDocumentStorage(String) method to force using a shared folder storage for exported document data. Note that currently, it is not possible to store exported documents data in a database.

                                In the attachment, you can find a sample project and a database backup that demonstrates this approach in action. Let us know if you have any further questions regarding this approach.

                                • Vasily (DevExpress Support) 09.06.2019

                                  We found an issue in the CustomDocumentStorageProvider.TryGet method's implementation that was provided in this thread. The issue made this method always return the false value, even if a document was stored in a database. This issue may cause problems with closing this report document or canceling its generation. So, we updated the code snippet and sample project provided in this thread to fix this issue.