2009-01-23 14 views
5

हमारे पास एक सी #/एएसपी.नेट (2.0) अनुप्रयोग है जो विंडोज सर्वर 2003 एंटरप्राइज़ संस्करण पर आईआईएस 6 पर चल रहा है। यह एप्लिकेशन ओलेडीबी का उपयोग कर एक्सेल फ़ाइलों को पढ़ता है, लेकिन ऐसे कई उदाहरण हैं जब हमें एप्लिकेशन के भीतर से "निर्दिष्ट त्रुटि" अपवाद मिल जाता है।सी #/एएसपी.नेट ओलेडब - एमएस एक्सेल "अनिर्दिष्ट त्रुटि"

फ़ाइल खोलने से पहले हमारे फ़ाइल अपलोड कोड द्वारा अस्थायी निर्देशिका में संग्रहीत है। चूंकि हमारे पास आईआईएस में अज्ञात पहुंच सक्षम है और चूंकि हम web.config में प्रतिरूपण का भी उपयोग करते हैं, इसलिए फ़ोल्डर C: \ Windows \ Temp \ में इंटरनेट अतिथि उपयोगकर्ता खाता (IUSR_ [MachineName]) के लिए उचित अनुमतियां बनाने में सक्षम होने के लिए, वहां फ़ाइलों को संशोधित करें और हटाएं।

OleDb कनेक्शन स्ट्रिंग:
प्रदाता = Microsoft.Jet.OLEDB.4.0; डेटा स्रोत = C: \ Windows \ अस्थायी \ tmp123.tmp.xls;
विस्तारित गुण = "एक्सेल 8.0; एचडीआर = हाँ; IMEX = 1;"

[ "डेटा स्रोत" ऊपर का श्रेय हर फ़ाइल के लिए बदल जाएगा।]

 
The stack trace of the exception is: 
    System.Exception: FileParsingFailed ---> System.Data.OleDb.OleDbException: 
    Unspecified error at 
    System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, 
    OleDbConnection connection) at 
    System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, 
    Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) at 
    System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection 
    owningConnection, DbConnectionPoolGroup poolGroup) at 
    System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection 
    owningConnection) at 
    System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection 
    outerConnection, DbConnectionFactory connectionFactory) at 
    System.Data.OleDb.OleDbConnection.Open() 

वर्कअराउंड:
अब तक, केवल वैकल्पिक हल हम साथ आ सकता है एक iisreset करने के लिए किया गया था (हम आईआईएस में प्रतिदिन एक बार होने के लिए कॉन्फ़िगर किया गया एप्लिकेशन पूल रीसाइक्लिंग भी है, लेकिन यह समस्या तब तक प्रतीत नहीं होती है क्योंकि समस्या कई बार लगातार जारी रहती है)। हालांकि यह करने के लिए एक अच्छी बात नहीं है, इससे और भी बदतर यह है कि हमारे पास उसी वेबसाइट पर अन्य एप्लिकेशन हैं जो आईआईएस को रीसेट करते समय प्रभावित होंगे।

सवाल:
1. हम इस त्रुटि कैसे ठीक करूं, क्योंकि यह कभी कभी होता है और हम एक पैटर्न नहीं दिख रहा है?
2. ओलेडीबी के अलावा सी #/एएसपी.नेट से एक्सेल फ़ाइलों को संसाधित करने के कोई बेहतर (और मुक्त) तरीके हैं? (हम सर्वर पर एमएस ऑफ़िस स्थापित करने के लिए है, क्योंकि यह माइक्रोसॉफ्ट द्वारा अनुशंसित नहीं है नहीं पसंद करते हैं)

हमारी सीमाएं:
1. हम एमएस ऑफ़िस 2003 (.xls) प्रारूप के साथ फंस रहे हैं और करने के लिए स्थानांतरित नहीं कर सकते एमएस ऑफिस 2007 (ओओएक्सएमएल) प्रारूप।
2. कारण हम सीएसवी का उपयोग नहीं करते हैं क्योंकि हमारे पास हमारे डेटा के भीतर कॉमा हो सकता है (अगर हम उद्धरण का उपयोग करते हैं तो भी इससे निपटने का दर्द होता है) और हम अपनी स्प्रेडशीट में कई वर्कशीट का भी उपयोग करते हैं (यह इसके साथ नहीं किया जा सकता है सीएसवी)।

धन्यवाद! :)

अद्यतन:
धन्यवाद, कीथ। यह जेट इंजन के साथ एक समस्या की तरह प्रतीत होता है, लेकिन हम इसका उपयोग (मुफ्त और उपयोग करने में आसान) की कमी के कारण करते हैं।
धन्यवाद, जो। लेकिन हम सीमित बजट पर हैं - इसलिए हम मुख्य रूप से मुफ्त उपकरण/पुस्तकालयों की तलाश में हैं।

उत्तर

2

मुझे संदेह है कि त्रुटि जेट ओएलडीडीबी इंजन के साथ कुछ करने के लिए है। यह काफी क्रैक है - अधिकांश डेस्कटॉप चीजों के लिए ठीक है लेकिन एंटरप्राइज़ डेटा इंटरचेंज के लिए ज्यादा उपयोग नहीं है।

यदि आप हाल ही में सी # 3/.NET 3.5 में अपग्रेड कर सकते हैं तो आप Office 2007 फ़ाइलों (.xlsx या .xlsm फ़ाइलों) को खोलने के लिए System.IO.Packaging लाइब्रेरी का उपयोग कर सकते हैं।

ये फ़ाइलें वास्तव में ज़िप हैं - उन्हें नाम बदलें। ज़िप और आप केवल एक्सएमएल फाइलों को अंदर देख सकते हैं।

एक्सएमएल फाइलों के प्रारूप काफी भयानक हैं (उदाहरण के लिए सेल टिप्पणियां वीएमएल हैं, उह!) लेकिन पठनीय।

वैकल्पिक रूप से अपने उपयोगकर्ताओं को एक्सेल टेबल को CSV के रूप में सहेजने के लिए प्राप्त करें। हालांकि मैं माइक्रोसॉफ्ट टेक्स्ट ड्राइवर डीबी प्रदाता से बचूंगा - यह बकवास है और यूनिकोड को संभाल नहीं सकता है। सीएसवी वैसे भी पढ़ने के लिए आसान हैं।

3

सुनिश्चित करें कि आप अपने कनेक्शन बंद कर रहे हैं।

उदाहरण के लिए जब एमएस एक्सेस एप्लिकेशन (जेट) विकसित करना यह त्रुटि तब होती है जब बहुत से कनेक्शन खुले रह जाते हैं। यह ठीक काम करता है (कभी-कभी आपका होता है) थोड़ी देर तक जब तक यह अधिकतम खुले कनेक्शन तक नहीं पहुंच जाता है।

2

मैं कुछ समय के लिए SpreadSheetGear.NET का उपयोग कर रहा हूं, ज्यादातर एक्सेल फाइलें बनाने के लिए, और यह अच्छी तरह से काम करता है।

http://www.spreadsheetgear.com/products/spreadsheetgear.net.aspx

यह द्विआधारी Excel फ़ाइल पढ़ने /, देशी .NET में लेखन सभी पिछले समस्याओं मैं OLE और जेट उपयोग करने के लिए पढ़ सकते हैं और Excel फ़ाइलों को बनाने का प्रयास सामना करना पड़ा सुलझाने प्रदान करता है।

विज़ुअल सी ++ एक्सप्रेस 2005 को पंजीकृत करने के लिए मूल संस्करण एक पेर्क के रूप में मुक्त होता था। यह अनदेखा था, इसलिए यह 2008 संस्करण के साथ अभी भी मौजूद हो सकता है या नहीं भी हो सकता है।

1

SpreadsheetGear for .NET आपको .NET से xls और xlsx कार्यपुस्तिकाओं के साथ काम करने के लिए एक एपीआई देता है। ओलेडीबी या एक्सेल COM ऑब्जेक्ट मॉडल (इस के कुछ सबूतों के लिए पढ़ना जारी रखें) से उपयोग करना और तेज़ करना आसान है।

अस्वीकरण: मैं खुद SpreadsheetGear LLC

नीचे, SpreadsheetGear के साथ 10 कॉलम कार्यपुस्तिका से एक 50,000 पंक्ति बनाएं डिस्क पर सहेजें, और उसके बाद OleDb और SpreadsheetGear का उपयोग कर संख्या योग करने के लिए कोड है। स्प्रेडशीट गियर 0.31 सेकंड में 500 के कोशिकाओं को ओलेडीबी के साथ 0.63 सेकेंड की तुलना में पढ़ता है - बस तेज़ी से दोगुना से अधिक। स्प्रेडशीट गियर वास्तव में ओलेडीबी के साथ कार्यपुस्तिका को पढ़ने के लिए कम समय में कार्यपुस्तिका बनाता है और पढ़ता है।

कोड नीचे है। आप live samples देख सकते हैं या free trial के साथ अपने आप को आजमाएं।

using System; 
using System.Data; 
using System.Data.OleDb; 
using SpreadsheetGear; 
using SpreadsheetGear.Advanced.Cells; 
using System.Diagnostics; 

namespace SpreadsheetGearAndOleDBBenchmark 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Warm up (get the code JITed). 
      BM(10, 10); 

      // Do it for real. 
      BM(50000, 10); 
     } 

     static void BM(int rows, int cols) 
     { 
      // Compare the performance of OleDB to SpreadsheetGear for reading 
      // workbooks. We sum numbers just to have something to do. 
      // 
      // Run on Windows Vista 32 bit, Visual Studio 2008, Release Build, 
      // Run Without Debugger: 
      // Create time: 0.25 seconds 
      // OleDb Time: 0.63 seconds 
      // SpreadsheetGear Time: 0.31 seconds 
      // 
      // SpreadsheetGear is more than twice as fast at reading. Furthermore, 
      // SpreadsheetGear can create the file and read it faster than OleDB 
      // can just read it. 
      string filename = @"C:\tmp\SpreadsheetGearOleDbBenchmark.xls"; 
      Console.WriteLine("\nCreating {0} rows x {1} columns", rows, cols); 
      Stopwatch timer = Stopwatch.StartNew(); 
      double createSum = CreateWorkbook(filename, rows, cols); 
      double createTime = timer.Elapsed.TotalSeconds; 
      Console.WriteLine("Create sum of {0} took {1} seconds.", createSum, createTime); 
      timer = Stopwatch.StartNew(); 
      double oleDbSum = ReadWithOleDB(filename); 
      double oleDbTime = timer.Elapsed.TotalSeconds; 
      Console.WriteLine("OleDb sum of {0} took {1} seconds.", oleDbSum, oleDbTime); 
      timer = Stopwatch.StartNew(); 
      double spreadsheetGearSum = ReadWithSpreadsheetGear(filename); 
      double spreadsheetGearTime = timer.Elapsed.TotalSeconds; 
      Console.WriteLine("SpreadsheetGear sum of {0} took {1} seconds.", spreadsheetGearSum, spreadsheetGearTime); 
     } 

     static double CreateWorkbook(string filename, int rows, int cols) 
     { 
      IWorkbook workbook = Factory.GetWorkbook(); 
      IWorksheet worksheet = workbook.Worksheets[0]; 
      IValues values = (IValues)worksheet; 
      double sum = 0.0; 
      Random rand = new Random(); 
      // Put labels in the first row. 
      foreach (IRange cell in worksheet.Cells[0, 0, 0, cols - 1]) 
       cell.Value = "Cell-" + cell.Address; 
      // Using IRange and foreach would be less code, 
      // but we'll do it the fast way. 
      for (int row = 1; row <= rows; row++) 
      { 
       for (int col = 0; col < cols; col++) 
       { 
        double number = rand.NextDouble(); 
        sum += number; 
        values.SetNumber(row, col, number); 
       } 
      } 
      workbook.SaveAs(filename, FileFormat.Excel8); 
      return sum; 
     } 

     static double ReadWithSpreadsheetGear(string filename) 
     { 
      IWorkbook workbook = Factory.GetWorkbook(filename); 
      IWorksheet worksheet = workbook.Worksheets[0]; 
      IValues values = (IValues)worksheet; 
      IRange usedRahge = worksheet.UsedRange; 
      int rowCount = usedRahge.RowCount; 
      int colCount = usedRahge.ColumnCount; 
      double sum = 0.0; 
      // We could use foreach (IRange cell in usedRange) for cleaner 
      // code, but this is faster. 
      for (int row = 1; row <= rowCount; row++) 
      { 
       for (int col = 0; col < colCount; col++) 
       { 
        IValue value = values[row, col]; 
        if (value != null && value.Type == SpreadsheetGear.Advanced.Cells.ValueType.Number) 
         sum += value.Number; 
       } 
      } 
      return sum; 
     } 

     static double ReadWithOleDB(string filename) 
     { 
      String connectionString = 
       "Provider=Microsoft.Jet.OLEDB.4.0;" + 
       "Data Source=" + filename + ";" + 
       "Extended Properties=Excel 8.0;"; 
      OleDbConnection connection = new OleDbConnection(connectionString); 
      connection.Open(); 
      OleDbCommand selectCommand =new OleDbCommand("SELECT * FROM [Sheet1$]", connection); 
      OleDbDataAdapter dataAdapter = new OleDbDataAdapter(); 
      dataAdapter.SelectCommand = selectCommand; 
      DataSet dataSet = new DataSet(); 
      dataAdapter.Fill(dataSet); 
      connection.Close(); 
      double sum = 0.0; 
      // We'll make some assumptions for brevity of the code. 
      DataTable dataTable = dataSet.Tables[0]; 
      int cols = dataTable.Columns.Count; 
      foreach (DataRow row in dataTable.Rows) 
      { 
       for (int i = 0; i < cols; i++) 
       { 
        object val = row[i]; 
        if (val is double) 
         sum += (double)val; 
       } 
      } 
      return sum; 
     } 
    } 
} 
1

मैं एक ही मुद्दा था और ऐसा लगता है कि यह पाश के हर यात्रा पर फ़ाइल के लिए कनेक्शन (xls या csv) बंद करके तय हो गई है। मुझे लगता है कि आप फ़ाइलों की सूची के माध्यम से भी लूपिंग कर रहे हैं और ओपन() प्रत्येक फ़ाइल के लिए एक नया कनेक्शन। यदि आप लूप के अंत में कनेक्शन को बंद कर देते हैं, तो समस्या दूर हो जाती है।

1

कनेक्शन समयऑट कारणों में से एक हो सकता है। पूछताछ करें कि डिबगिंग द्वारा एप्लिकेशन में कितना समय निकालना है।

1

लगता है जैसे मुझे मिल गया यह गलत, असल में क्या CRice कहा Problem with OleDbConnection, Excel and connection pooling

देखते हैं, लेकिन वहाँ है, जब OleDbDataAdapter (String, String) निर्माता एक्सेल-ConnectionString साथ कहा जाता है Dispose() के कार्यान्वयन में एक समस्या लगती है के रूप में implicitely बनाया कनेक्शन स्पष्ट रूप से बंद नहीं है।

वैकल्पिक हल सभी कॉल्स OleDbDataApater उपयोगों (आप उपयोग कर रहे थे रैप करने के लिए है ...एक अलग

using (var conn = new OleDbConnection(connectionString)) 

और साथ सामान के रूप में यह IDisposable लागू करता है) तो OleDbDataAdapter (String, OleDbConnection) निर्माता कहते हैं।

संपादित करें: मैं निपटाने पर बंद करने कनेक्शन के बारे में गलत था। conn.Dispose() कनेक्शन बंद नहीं करता है, इसलिए using (var conn = new OleDbConnection(connectionString)) के अंदर आपको अभी भी conn.Close() करने की आवश्यकता है।

संबंधित मुद्दे