Lenka.Guo 发表于 2020-8-31 15:13:39

在线设计器如何实现将报表保存到数据库中并从数据库中读取

附件


在线设计器是基于MVC 项目开发的,默认的是将报表保存到服务器的文件夹上面。但往往有很多应用场景是需要将报表保存到数据库是比较常用的应用场景。
所以就需要去修改Starup.cs中reporting文件的配置。

1, 修改app.UseReporting()调用 UserCustomStore,并在 UseCustomerStore中添加 ResourceService 的Model类。
   public void Configuration(IAppBuilder app)
                {
                        app.UseErrorPage();

                        var dataSetsService = new FileSystemDataSets(DataSetsRootDirectory);
                        var templatesService = new FileSystemTemplates(TemplatesRootDirectory);
                        app.Use((context, next) =>
                        {
                                context.Set(typeof(IDataSetsService).ToString(), dataSetsService);
                                context.Set(typeof(ITemplatesService).ToString(), templatesService);
                                return next.Invoke();
                        });

                        //var resourcesService = new SQLiteResourcesService(Path.Combine(Directory.GetCurrentDirectory(), "ResourcesService" + Path.DirectorySeparatorChar + "reports.db"));
                        var resourcesService = new SQLExpressResourcesService();

                        //app.UseDesigner(config => config.UseFileStore(ResourcesRootDirectory, false));
                        app.UseDesigner(config => {
                                config.UseCustomStore(resourcesService);
                        });

                        //app.UseReporting(config => config.UseFileStore(ResourcesRootDirectory));
                        app.UseReporting(config => config.UseCustomStore((reportId) =>
                        {
                                var rep = resourcesService.GetReport(reportId);
                                return rep;
                        }));

                        app.UseStaticFiles(new StaticFileOptions { FileSystem = new PhysicalFileSystem(String.Format(@"{0}.\wwwroot\", HttpRuntime.AppDomainAppPath)) });
                }
        }
2. 新建SQLiteReportService 继承 IResourceService

在这个类里面,我们实现连接 SQLite数据库,并根据报表ID,查找出报表文件后,并将流数据还原成报表对象。

using GrapeCity.ActiveReports.Aspnet.Designer.Services;
using GrapeCity.ActiveReports.PageReportModel;
using GrapeCity.ActiveReports.Rdl.Tools;
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.IO;

namespace WebDesigner_MVC
{
    public class SQLiteResourcesService : IResourcesService
    {
      private string ConnString { get; set; }

      public SQLiteResourcesService(string dbPath)
      {
            ConnString = $"Filename={dbPath};Mode=ReadWriteCreate";
            using (var conn = new SqliteConnection(ConnString))
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                  cmd.CommandText = "CREATE TABLEIF NOT EXISTS reports(id INTEGER PRIMARY KEY, name TEXT, layout BLOB, temp INTEGER, reportType TEXT);";
                  cmd.ExecuteNonQuery();
                }
            }
      }

      public void DeleteReport(string id)
      {
            using (var conn = new SqliteConnection(ConnString))
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                  cmd.CommandText = $"Delete from reports where id={id}";
                  cmd.ExecuteNonQuery();
                }
            }
      }

      public Uri GetBaseUri()
      {
            throw new NotImplementedException();
      }

      public byte[] GetImage(string id, out string mimeType)
      {
            throw new NotImplementedException();
      }

      public IImageInfo[] GetImagesList()
      {
            return new IImageInfo[] { };
      }

      public Report GetReport(string id)
      {
            // work-around the report processing that automatically adds .rdlx extension
            if (id.EndsWith(".rdlx"))
            {
                id = id.Substring(0, id.IndexOf(".rdlx"));
            }
            using (var conn = new SqliteConnection(ConnString))
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                  cmd.CommandText =
                  $"SELECT id, layout from reports where id = $id";
                  cmd.Parameters.AddWithValue("$id", id);
                  using (var reader = cmd.ExecuteReader())
                  {
                        while (reader.Read())
                        {
                            using (var readStream = reader.GetStream(1))
                            using (var outputStream = new MemoryStream())
                            {
                              readStream.CopyTo(outputStream);
                              return ReportConverter.FromXML(outputStream.ToArray());
                            }
                        }
                  }

                }
            }
            return null;
      }

      public IReportInfo[] GetReportsList()
      {
            var reportList = new List<ReportInfo>();
            using (var conn = new SqliteConnection(ConnString))
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                  cmd.CommandText = "Select id, name, reportType from reports where temp = 0";
                  using (var reader = cmd.ExecuteReader())
                  {
                        while (reader.Read())
                        {
                            reportList.Add(new ReportInfo() { Id = reader.GetString(0), Name = reader.GetString(1), Type = reader.GetString(2) });
                        }
                  }
                }
            }
            return reportList.ToArray();
      }

      public Theme GetTheme(string id)
      {
            throw new NotImplementedException();
      }

      public IThemeInfo[] GetThemesList()
      {
            return new IThemeInfo[] { };
      }

      public string SaveReport(string name, Report report, bool isTemporary = false)
      {
            var rdlBytes = ReportConverter.ToXml(report);
            string rptType = report.Body.ReportItems.Count > 0 && report.Body.ReportItems.GetReportItemTypeName() == "FixedPage" ? "FPL" : "CPL";
            using (var conn = new SqliteConnection(ConnString))
            using (var repStream = new MemoryStream(rdlBytes))
            {
                conn.Open();
                var insertCommand = conn.CreateCommand();
                insertCommand.CommandText =
                $"INSERT INTO reports(name, layout, temp, reportType) VALUES (\"{name}\", zeroblob($length), {(isTemporary ? 1 : 0)}, \"{rptType}\"); SELECT last_insert_rowid();";
                insertCommand.Parameters.AddWithValue("$length", repStream.Length);
                var rowid = (long)insertCommand.ExecuteScalar();
                using (var writeStream = new SqliteBlob(conn, "reports", "layout", rowid))
                {
                  repStream.CopyTo(writeStream);
                }
                return rowid.ToString();
            }

      }

      public string UpdateReport(string id, Report report)
      {
            var rdlBytes = ReportConverter.ToXml(report);
            using (var conn = new SqliteConnection(ConnString))
            using (var repStream = new MemoryStream(rdlBytes))
            {
                conn.Open();
                using (var writeStream = new SqliteBlob(conn, "reports", "layout", long.Parse(id)))
                {
                  repStream.CopyTo(writeStream);
                }
                return id;
            }

      }
    }
}





Popeye 发表于 2021-8-5 13:20:04

好东西,正好需要,先mark一下。
我需要把报表文件及主题文件保存在阿里云的OSS中。

James.Lv 发表于 2021-8-5 16:04:53

Popeye 发表于 2021-8-5 13:20
好东西,正好需要,先mark一下。
我需要把报表文件及主题文件保存在阿里云的OSS中。

:hjyzw:

Popeye 发表于 2021-8-5 16:45:21

本帖最后由 Popeye 于 2021-8-5 16:46 编辑

James 版主好!我下载了这个范例,但是里面的 SQLExpressResourcesService 和 SQLiteResourcesService 服务类中都没有实现 获取 Theme 和 Image 的方法,请问,能给出完整的范例么?
      public byte[] GetImage(string id, out string mimeType)
      {
            throw new NotImplementedException();
      }

      public IImageInfo[] GetImagesList()
      {
            return new IImageInfo[] { };
      }

      public Theme GetTheme(string id)
      {
            throw new NotImplementedException();
      }

      public IThemeInfo[] GetThemesList()
      {
            return new IThemeInfo[] { };
      }

James.Lv 发表于 2021-8-6 18:41:44

Popeye 发表于 2021-8-5 16:45
James 版主好!我下载了这个范例,但是里面的 SQLExpressResourcesService 和 SQLiteResourcesService 服务 ...

这个我们这边整理个示例到时候发您

Popeye 发表于 2021-8-14 16:00:31

James.Lv 发表于 2021-8-6 18:41
这个我们这边整理个示例到时候发您

这个ResourceService 我已全部实现完成了,但是遇到一个无法在设计器中预览报表的问题,请麻烦帮我看看吧:


https://gcdn.grapecity.com.cn/forum.php?mod=viewthread&tid=97908&page=1&extra=#pid412931

James.Lv 发表于 2021-8-16 09:26:56

Popeye 发表于 2021-8-14 16:00
这个ResourceService 我已全部实现完成了,但是遇到一个无法在设计器中预览报表的问题,请麻烦帮我看看吧 ...

好的我们在您的求助贴中帮您解决:mj72:

wengMQ 发表于 2022-3-2 23:32:58

获取 Theme 和 Image 的方法,请问,能给出完整的范例么?

Bella.Yuan 发表于 2022-3-3 12:15:18

wengMQ 发表于 2022-3-2 23:32
获取 Theme 和 Image 的方法,请问,能给出完整的范例么?

您好,该问题已在下面链接回复,稍后整理好发您。
https://gcdn.grapecity.com.cn/forum.php?mod=viewthread&tid=142218

tangke888 发表于 2024-6-8 10:43:31

可以更新一个 AR18.0的版本,做参考?
页: [1] 2
查看完整版本: 在线设计器如何实现将报表保存到数据库中并从数据库中读取