2010-12-14 66 views
2

我想上传一个约600MB的压缩文件到SQL 2008 FILESTREAM表,我得到OutOfMemoryException。我正在使用SqlFileStream类来上传文件(如本教程中所述 - http://www.aghausman.net/dotnet/saving-and-retrieving-file-using-filestream-sql-server-2008.html)。我有一个32位的Vista机器4GB内存,如果该事项和我使用VS 2010,实体框架4OutOfMemoryException当使用SQL文件流

这里是我的代码片段 -

public static void AddItem(RepositoryFile repository) 
    { 
     var contents = repository.Data; // I get the exception at this line. 
     repository.Data = System.Text.Encoding.ASCII.GetBytes("0x00"); 

     using (var scope = new TransactionScope()) 
     { 
      using (var db = new MyEntities()) 
      { 
       db.RepositoryTable.AddObject(repository); 
       db.SaveChanges(); 
      } 

      using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) 
      using (var cmd = new SqlCommand("SELECT Data.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM dbo.RepositoryTable", con)) 
      { 
       cmd.Connection.Open(); 
       using (var reader = cmd.ExecuteReader()) 
       { 
        while (reader.Read()) 
        { 
         var path = reader.GetString(0); 
         var transactionContext = reader.GetSqlBytes(1).Buffer; 
         var fileStream = new SqlFileStream(path, transactionContext, FileAccess.Write); 

         fileStream.Write(contents, 0, contents.Length); 
         fileStream.Close(); 
        } 
       } 
      } 

      scope.Complete(); 
     } 
    } 

如何上传文件时不进行错误?

谢谢!

回答

0

我想出了这个问题。这里是我的代码 -

private void AddFile() 
    { 
     if (!fupFile.HasFile) 
     { 
      lblMessage.Text = "Please select a file.";     
      return; 
     } 

     var data = new byte[(int) fupFile.FileContent.Length]; 
     fupFile.FileContent.Read(data, 0, data.Length); 

     if (fupFile.FileContent.Length > 0) 
     { 
      var repositoryFile = new Repository 
            { 
             ID = Guid.NewGuid(), 
             Name = Path.GetFileName(fupFile.PostedFile.FileName),            
             Data = System.Text.Encoding.ASCII.GetBytes("0x00") 
            }; 

      RepositoryController.AddItem(repositoryFile, data); // Calling DAL class. 
     } 
    } 

// DAL method 
public static void AddItem(RepositoryFile repository, byte[] data) 
{ 
    using (var scope = new TransactionScope()) 
    { 
     using (var db = new MyEntities()) // DBContext 
     { 
      db.RepositoryTable.AddObject(repository); 
      db.SaveChanges(); 
     } 

     using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) 
     using (var cmd = new SqlCommand(string.Format("SELECT Data.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM dbo.RepositoryTable WHERE ID='{0}'", repository.ID), con)) // "Data" is the column name which has the FILESTREAM. Data.PathName() gives me the local path to the file. 
     { 
      cmd.Connection.Open(); 
      using (var reader = cmd.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        var path = reader.GetString(0); 
        var transactionContext = reader.GetSqlBytes(1).Buffer; 
        var fileStream = new SqlFileStream(path, transactionContext, FileAccess.Write); 

        fileStream.Write(contents, 0, contents.Length); //Write contents to the file. 
        fileStream.Close(); 
       } 
      } 
     } 

     scope.Complete(); 
    } 
} 
0

了解发生错误的位置可以帮助您找到解决方案。对此做出的一项改变可能有助于大块写入文件(不要一次写完,循环写入一次)。这为流提供了刷新并因此释放系统资源的机会。

+0

我已经更新了片段,以指示它引发错误(var contents = repository.Data;)的位置。实际上我做了一个副本,并在第一次运行时向FILESTREAM写入一个字节,并在稍后使用副本写入实际字节。我认为在用单个字节覆盖字节之前,内存会保存文件字节的两个副本(一个位于repository.Data中,另一个位于内容中)。我认为这是造成这个问题的原因。我也在寻找如何上传大块文件。 – tempid 2010-12-14 16:23:03

+0

什么是repository.Data,它是如何设置的? – 2010-12-14 16:30:55

+0

为不完整的细节道歉。 repository.Data被设置在我的aspx的代码隐藏中。我已经解决了我的问题,并使用新代码发布了新帖子。感谢Brian! – tempid 2010-12-14 18:53:06

相关问题