0

我正在为这种情况寻找一个好的解决方案:

  • 我有一个带有 SQL Server 2008 R2 后端的 asp.net 应用程序。
  • 我需要允许用户上传文件并将其保存以供以后检索。
  • 我还需要解析这个文件以便在数据库端进行查询。所以我需要这个文件中的数据作为数据表和来自 sql 的数据来组合结果。

所以这就是我的想法:

  1. 将excel 文件存储在 SQL Server 中varbinary(max)- 这将允许稍后通过 .net 轻松检索文件。
  2. 解析:一种方法是在用户上传文件时使用openxml或一些第3方库将其解析为数据表并将其传递给将返回结果集的存储过程。

我不喜欢这种方法,因为这意味着我们必须将大量数据传递给数据库两次(第一次传递整个文件时,第二次传递数据集时。

关于如何更有效地做到这一点的任何建议?是否可以使用以下方式从 varbinary max 读取数据:

SELECT *
FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0', 
                    'Data Source=D:\TestJET.xls;
                    Extended Properties=''Excel 12.0;HDR=NO;IMEX=1;ImportMixedTypes=Text''')...[Sheet1$]

但没有实际创建文件?

或者也许可以不将整个文件传递给数据库,而是从数据表中构造回 excel 文件?

或者也许varbinary(max)不是最好的解决方案,而是更好地使用不同的数据类型,如 XML?

Excel 文件非常简单。一张没有宏或公式的样式表。(虽然不能转换为 CSV)文件大小为 200-800kb。

4

3 回答 3

1

您从数据库构建 excel 文件的想法很有趣 - 这表明获取上传的相同文件并不重要,只需包含相同信息的文件即可。那是对的吗?

如果是这样,我会在服务器上解析上传文件(我喜欢用于 C# excel 工作的ClosedXML),将相关数据以查询友好的形式存储在数据库中,然后丢弃原始文件。当用户要求返回文件时,为他们创建一个具有正确内容的新文件。

小心 XML 数据类型列 - 它们对您可以使用它们执行的操作有限制。

于 2012-05-13T08:44:31.293 回答
0

您可以使用 FileUpload 控件将文件上传到您的服务器,然后可以在每次需要时检索该文件。

从那里您可以使用 OleDbConnection 读取 excel 文件,将每个获取的记录添加到列表中以逐个迭代,然后将它们插入到您的数据库中。

这是一个使用三个类的小示例:CConexion(处理 OleDbConnection 进程)、ExcelParser(读取获取的记录并将其插入到您的数据库中,以便您可以在需要时对其进行查询)和 ExcelRecord,它表示每个注册表上的数据容器你的 Excel 文件。

当您的计算机上有 MS Office Excel 2010 时,会安装这些 OleDb 库。我已经测试了代码并且运行良好。

该 excel 文件在示例中称为 Hoja1.xlsx,并存储在 TestApp 根目录下名为 Files 的文件夹中,当您打开它时,会出现三个记录,每个记录有两个字段(A1,B1),(A2,B2) ,(A3,B3) 在文件的第一张也称为 Hoja1.xlsx

    ''CConexion Class:

    Imports System.Data.SqlClient
    Imports System.Data.OleDb
    Imports System.Data

    Public Class CConexion

    #Region "Private Variables"

        Dim sOleDbConnectionString As String = String.Empty
        Dim conexionOleDb As New OleDbConnection()

    #End Region

    #Region "Con_Ole"

        Public Interface IConexionOleDb

            Property retConexionOleDb() As OleDbConnection
            Sub retOpenOleDb()
            Sub retCloseOleDb()

        End Interface

        Public Property retConexionOleDb() As OleDbConnection

            Get
                Return conexionOleDb
            End Get
            Set(ByVal value As OleDbConnection)

            End Set

        End Property

        Public Sub retOpenOleDb()

            If Not conexionOleDb.State = System.Data.ConnectionState.Open Then
                conexionOleDb.Open()
            End If

        End Sub

        Public Sub retCloseOleDb()

            If Not conexionOleDb.State = ConnectionState.Closed Then
                conexionOleDb.Close()
            End If

        End Sub

    #End Region

    #Region "Constructors"

        Public Sub New()

        End Sub

        Public Sub New(ByVal rutaOleDb As String)

            sOleDbConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" _
                                                        & "Data Source=" & rutaOleDb _
                                                        & ";" & "Extended Properties=Excel 12.0;"
            conexionOleDb.ConnectionString = sOleDbConnectionString

        End Sub

    #End Region

    End Class

    ''ExcelRecord Class:

    Public Class ExcelRecord

        Private _RId As Short = 0
        Public Property RId() As Short
            Get
                Return _RId
            End Get
            Set(ByVal value As Short)
                _RId = value
            End Set
        End Property

        Private _RText As String = String.Empty
        Public Property RText() As String
            Get
                Return _RText
            End Get
            Set(ByVal value As String)
                _RText = value
            End Set
        End Property

        Public Sub New()

        End Sub

        Public Sub New(ByVal Rid As Short, ByVal RText As String)
            Me.RId = Rid
            Me.RText = RText
        End Sub

    End Class

    ''ExcelParser Class:

    Imports System.Data.OleDb
    Imports System.Collections.Generic

    Public Class ExcelParser

        Private Function InsertRecords(ByVal objExcelRecords As List(Of ExcelRecord)) As Boolean
        ''Your code for insertion here
            Return True
        End Function

        Public Function ReadExcel(ByVal filePath As String) As Short

            Dim cn As New CConexion(filePath)
            Dim dr As OleDbDataReader
            Dim OperationState As Boolean = False
            Dim objExcelRecords As New List(Of ExcelRecord)

            Try

                Dim cmd As New OleDbCommand("Select * from [Hoja1$]", cn.retConexionOleDb)

                cn.retOpenOleDb()
                dr = cmd.ExecuteReader

                While dr.Read    

                    Dim objExcelRecord As New ExcelRecord(CShort(dr(0)), CStr(dr(1)))
                    objExcelRecords.Add(objExcelRecord)

                End While

                OperationState = InsertRecords(objExcelRecords)
                CType(dr, IDisposable).Dispose()

            Catch ex As Exception

            Finally

                cn.retCloseOleDb()
                cn.retConexionOleDb.Dispose()

            End Try

            Return OperationState

        End Function

    End Class


''Test Page ExcelReader.aspx.vb
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If Not Page.IsPostBack Then

            Dim filePath As String = Server.MapPath("~\Files\Hoja1.xlsx")
            Dim objExcelParser As New ExcelParser()

            If objExcelParser.ReadExcel(filePath) Then
                Response.Write("Read!")
            Else
                Response.Write("No Read!")
            End If

        End If

    End Sub

让我知道这是否适合您。希望能帮助到你。

于 2012-05-13T07:18:01.540 回答
0

您可能希望查看 SQL 2008 r2 的 FILESTREAM 功能以将文件存储在服务器中。这是一个概述和一篇很好的博客文章。我不确定您的文件类型或您需要从中删除什么,但您可以选择使用批量插入,或者您已经指出 OPENDATASOURCE 或稍后执行进程,然后使用 FILESTREAM 中的 ID 加载数据以链接数据。

于 2012-05-12T19:56:51.967 回答