代码之家  ›  专栏  ›  技术社区  ›  James Alexander

SQL Server 2008:文件流插入失败w/.NET 3.5SP1

  •  1
  • James Alexander  · 技术社区  · 16 年前

    我已经配置了一个db w/a FileStream组,并且在它上面有一个表w/文件类型。尝试插入流文件时,在创建表行之后,我的查询将读取文件路径,缓冲区将返回空文件路径。我似乎不明白为什么。以下是表创建脚本:

        /****** Object:  Table [dbo].[JobInstanceFile]    Script Date: 03/22/2010 18:05:36 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    SET ANSI_PADDING ON
    GO
    
    CREATE TABLE [dbo].[JobInstanceFile](
        [JobInstanceFileId] [int] IDENTITY(1,1) NOT NULL,
        [JobInstanceId] [int] NOT NULL,
        [File] [varbinary](max) FILESTREAM  NULL,
        [FileId] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
        [Created] [datetime] NOT NULL,
     CONSTRAINT [PK_JobInstanceFile] PRIMARY KEY CLUSTERED 
    (
        [JobInstanceFileId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY] FILESTREAM_ON [JobInstanceFilesGroup],
    UNIQUE NONCLUSTERED 
    (
        [FileId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY] FILESTREAM_ON [JobInstanceFilesGroup]
    
    GO
    
    SET ANSI_PADDING OFF
    GO
    
    ALTER TABLE [dbo].[JobInstanceFile] ADD  DEFAULT (newid()) FOR [FileId]
    GO
    

        /****** Object:  StoredProcedure [dbo].[JobInstanceFileCreate]    Script Date: 03/22/2010 18:06:23 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    create proc [dbo].[JobInstanceFileCreate]
    
        @JobInstanceId int,
        @Created datetime
    
        as
    
        insert into JobInstanceFile (JobInstanceId, FileId, Created)
        values (@JobInstanceId, newid(), @Created)
    
        select scope_identity()
    GO
    

    最后,我使用的代码是:

        public int CreateJobInstanceFile(int jobInstanceId, string filePath)
            {
                using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConsumerMarketingStoreFiles"].ConnectionString))
                using (var fileStream = new FileStream(filePath, FileMode.Open))
                {
                    connection.Open();
    
                    var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted);
    
                    try 
                    {
                        //create the JobInstanceFile instance
                        var command = new SqlCommand("JobInstanceFileCreate", connection) { Transaction = tran };
                        command.CommandType = CommandType.StoredProcedure;
                        command.Parameters.AddWithValue("@JobInstanceId", jobInstanceId);
                        command.Parameters.AddWithValue("@Created", DateTime.Now);
    
                        int jobInstanceFileId = Convert.ToInt32(command.ExecuteScalar());
    
                        //read out the filestream transaction context to stream the file for storage
                        command.CommandText = "select [File].PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() from JobInstanceFile where JobInstanceFileId = @JobInstanceFileId";
                        command.CommandType = CommandType.Text;
                        command.Parameters.AddWithValue("@JobInstanceFileId", jobInstanceFileId);
    
                        using (SqlDataReader dr = command.ExecuteReader())
                        {
                            dr.Read();
    
                            //get the file path we're writing out to
                            string writePath = dr.GetString(0);
    
                            using (var writeStream = new SqlFileStream(writePath, (byte[])dr.GetValue(1), FileAccess.ReadWrite))
                            {
                                //copy from one stream to another
                                byte[] bytes = new byte[65536];
                                int numBytes;
                                while ((numBytes = fileStream.Read(bytes, 0, 65536)) > 0)
                                    writeStream.Write(bytes, 0, numBytes);
                            }
                        }
    
                        tran.Commit();
    
                        return jobInstanceFileId;
                    }
                    catch (Exception e)
                    {
                        tran.Rollback();
                        throw e;
                    }
                }
            }
    

    有人能告诉我我做错了什么吗。在代码中,以下表达式为文件路径返回null,不应为:

    //获取要写入的文件路径

    服务器与运行代码的计算机不同,但必要的共享似乎是有序的,我还运行了以下程序:

    EXEC sp\u configure filestream\u access\u level,2级

    任何帮助都将不胜感激。谢谢!

    1 回复  |  直到 16 年前
        1
  •  5
  •   Pawel Marciniak    16 年前

    不能以空值打开SqlFileStream。将INSERT语句更改为set File=0x,它将开始工作。

    附言 一些性能注意事项:

    1. OUTPUT clause 返回新插入的blob的事务上下文和文件路径。
    2. 如果您不想从SqlFileStream读取,请以只写方式打开它。在这种情况下,这可能不是什么大问题,因为您打开的文件是空的。但是,如果您要更新一个大文件,打开它进行读写将使Sql先复制整个文件,然后才允许您使用它。