C# 在SQL Server中存储excel文件

C# 在SQL Server中存储excel文件,c#,asp.net,sql,sql-server,sql-server-2008-r2,C#,Asp.net,Sql,Sql Server,Sql Server 2008 R2,我正在为这个场景寻找一个好的解决方案: 我有一个带有SQL Server 2008 R2后端的asp.net应用程序 我需要允许用户上传一个文件,并保存为以后检索 我还需要解析这个文件,以便在数据库端进行查询。所以我需要这个文件中的数据作为datatable,也需要sql中的数据来组合结果 以下是我的想法: 将excel文件以varbinary(max)的形式存储在SQL Server中-这将允许以后通过.net轻松检索文件 解析:一种方法是在用户上传文件时,使用openxml或某些第三方库

我正在为这个场景寻找一个好的解决方案:

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

  • 将excel文件以
    varbinary(max)
    的形式存储在SQL Server中-这将允许以后通过.net轻松检索文件
  • 解析:一种方法是在用户上传文件时,使用openxml或某些第三方库将其解析到datatable中,并将其传递给存储过程,存储过程将返回resultset
  • 我不喜欢这种方法,因为这意味着我们必须向数据库传递大量数据两次(第一次是在传递整个文件时,第二次是在传递数据集时)

    关于如何更有效地执行此操作,您有什么建议吗?是否可以使用以下方法从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$]
    
    但实际上没有创建一个文件

    或者可以不将整个文件传递给数据库,而是从datatable构造excel文件

    或者,
    varbinary(max)
    不是最好的解决方案,最好使用不同的数据类型,比如XML


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

    您可能希望查看SQL 2008 r2的FILESTREAM功能,以便将文件存储在服务器中。这是一个很好的示例。我不确定您的文件类型或需要从中获取什么,但您可以选择使用大容量插入,或者正如您已经指出的那样,使用OPENDATASOURCE或稍后执行流程使用文件流中的ID加载数据以链接数据。

    您可以使用文件上载控件将文件上载到服务器,然后每次需要时都可以检索该文件

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

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

    这些OleDb库是在计算机上安装MS Office Excel 2010时安装的。我已经测试了代码,效果良好

    在本例中,excel文件名为Hoja1.xlsx,存储在TestApp根目录下名为Files的文件夹中。打开该文件时,在文件的第一页(也称为Hoja1.xlsx)上有三条记录,每个记录有两个字段(A1、B1)、(A2、B2)、(A3、B3)

        ''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
    

    让我知道这是否对您有效。希望能有所帮助。

    您从数据库构建excel文件的想法很有意思-这表明将上载的相同的文件取回并不重要,只是一个包含相同信息的文件。对吗

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


    使用XML数据类型列时要小心—它们与您可以使用它们的功能有关。

    excel文件数据可以结构化?它是什么类型的表?是否可以将excel文件保留在共享驱动器上,只存储路径名?如果需要将其存储在数据库中,是否可以立即加载数据,然后在非工作时间批量加载excel?