2010-12-14 68 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

相關問題