-2

如何将 Excel 文件从 WinForms 客户端传递到 WCF 服务并传递到 SQL Server 表中?

任何人都可以提供任何指导、代码或建议吗?

  1. 将 Excel 文件作为参数的 WCF 服务合同和实现
  2. 合同实施应将该 Excel 文件插入到 SQL Server 中的 varbinary(MAX) 列中。
4

2 回答 2

2
  • 这是一篇解决您问题的 WCF 部分的帖子。
  • 将文件发送到服务器后,您可以使用FileHelpers.net将该文件解析为对象。

我不在乎您的要求是什么,不要将 excel 文档插入到 sql server varbinary(max) 列中。要求应该说“上传一个 Excel 文档,将其内容插入数据库。但是,我们需要将原始 excel 文件与数据库中的数据相关联,这样我们就可以拒绝任何关于我们的过程失败的说法,并有一个验证机制。”

  • 创建另一个名为 EXCEL_IMPORT 的表或具有
    或多或少以下列的表

检查我放在那里的扩展属性以获得列说明

create table EXCEL_IMPORT 
(
     ImportID   int identity(1,1) NOT NULL CONSTRAINT [PK_EXCEL_IMPORT] PRIMARY KEY,
     FileName_Incoming  varchar(max),
     FilePath_Internal  varchar(max),
     FileName_Internal  varchar(max),
     FileRowCount   int NOT NULL CONSTRAINT [CK_EXCEL_IMPORT_FileRowCount] CHECK  (FileRowCount >= 0),
     ImportDate datetime NOT NULL CONSTRAINT [DF_EXCEL_IMPORT_ImportDate] DEFAULT(getdate())
)

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'The location on the client computer i.e. C:\Users\jimmy\Desktop\iHeartExcel.xls' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'EXCEL_IMPORT', @level2type=N'COLUMN',@level2name=N'FileName_Incoming'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'The folder on your fileshare the file is in (this is incase you decide to change the fileshare name)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'EXCEL_IMPORT', @level2type=N'COLUMN',@level2name=N'FilePath_Internal'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'The unique filename that you decided on in the fileshare i.e. 2012_04_20_11_34_59_0_71f452e7-7cac-4afe-b145-6b7557f34263.xls' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'EXCEL_IMPORT', @level2type=N'COLUMN',@level2name=N'FileName_Internal'
  • 接下来,编写一个将 excel 文件复制到文件共享位置的过程,并创建一个唯一的文件名。此时,您有一个代表文件的对象、文件本身以及有关您放置文件的位置的所有信息。
  • 创建一个模仿 excel 电子表格列的表,并在其末尾添加一个 ImportID,该表引用回上面定义的 excel_import 表以及一个身份主键。
  • 之后,编写一个将对象插入到具有指定关系的数据库中的过程。这将根据您当前的设置而有所不同。
  • 最后,您应该有一个包含所有 Excel 数据的键控表,该表引用导入表中指向磁盘上文件的行。

其他一些想法

  • 我会考虑不允许修改表中的excel数据。将其以计算形式复制到另一个表中。有时这不会因为数据量大,但您在这里所做的是构建可证明的数据链回原始源,有时拥有未受污染的文件副本和 sql 副本是有意义的。
  • 您的第一反应是“但是所有的 excel 文件都不一样!” 如果是这种情况,您只需创建指向磁盘上文件的导入表(假设它们应该不同)。如果它们应该是相同的,您只需要更多的错误检查。
  • 将二进制文件保存在数据库中会产生后果。即备份大小和那个 sql 不能真正索引这些类型的列。每次插入文件时,您对该表的遍历也会变慢,并且通常您不希望这样。(你不能对磁盘上的文件做更多或更少的事情,而不是对二进制文件做更多或更少)
  • 在共享的文件名中使用带有前置日期的 GUID。无论如何,您永远不会搜索这些文件,如果您需要按日期执行,您可以使用文件名。这使得名称全局唯一,以防其他进程也需要在此处写入。
  • 我知道这不是你所要求的,但我以前曾走这条路,后果很严重。我已经使用上述方法导入了数百万个文件,并且没有出现重大的流程问题。
  • 当要求不可行时说出来。建议更便宜或更容易做同样事情的替代方案(使用可测试/可扩展之类的词)。
于 2012-04-20T15:58:39.780 回答
0

我相信那里的专家可以对此进行改进,但这里是基础知识......

在服务器上

1a。将新的 OperationContract 添加到您的接口(例如 IService.cs)

[OperationContract]
string UploadBinaryFile(byte[] aByteArray);

1b。在您的合同实施中插入 SQL Server 表(例如 Service.cs)

public string UploadBinaryFile(byte[] aByteArray)
{
    try
    {
        SqlConnection conn = new SqlConnection();
        conn.ConnectionString = MyConnectionString; // from saved connection string
        conn.Open();
        using (SqlCommand cmd = new SqlCommand("INSERT INTO MyTestTable(BinaryFile) VALUES (@binaryfile)", conn))
        {
            cmd.Parameters.Add("@binaryfile", SqlDbType.VarBinary, -1).Value = aByteArray;
            cmd.ExecuteNonQuery();
        }

        return "1"; // to me, this indicates success
    }
    catch (Exception ex)
    {
        return "0: " + ex.Message; // return an error indicator + ex.message
    }
}

在客户端

2a. 使用 OpenFileDialog 组件通过大多数 Windows 应用程序使用的标准对话框浏览文件系统上的文件。

if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
    txtUploadFilePath.Text = openFileDialog1.FileName;
}

2b。将文件内容加载到字节数组中

var byte[] BinaryFile = System.IO.File.ReadAllBytes(txtUploadFilePath.Text);

2c。调用你的 WCF 合约,传入字节数组

string UploadResponse = client.UploadBinaryFile(BinaryFile);

它正在工作......是的:-)

于 2012-04-23T14:17:17.953 回答