2017-07-19 126 views
0

我使用Microsoft SQL Server遷移助理將Access數據庫遷移到SQL。SqlDataReader拋出「當無數據存在時無效嘗試讀取」但OleDbReader不會

現在,我無法讀取數據。

return reader.GetInt32(0);拋出Invalid attempt to read when no data is present異常後行檢索。如果我將CommandBehavior.SequentialAccess添加到我的命令中,則可以每次讀取行,

數據

查詢(在SQL Management Studio中):

SELECT * 
FROM Products2 
WHERE Products2.PgId = 337; 

沒有什麼特別之處排32,如果我顛倒順序,但仍排32,殺死它。

row 32

行265,只是爲了好措施。

row 265

代碼

查詢:

SELECT * 
FROM Products2 
WHERE Products2.PgId = @productGroupId; 

參數:

Name = "productGroupId" 
Value = 337 

執行:

public async Task ExecuteAsync(string query, Action<IDataReader> onExecute, params DataParameter[] parameters) 
{ 
    using(var command = builder.BuildCommand(query)) 
    { 
     foreach(var parameter in parameters) 
      command.AddParameter(parameter); 
     if(!connection.IsOpen) 
      connection.Open(); 
     await Task.Run(async() => 
     { 
      using(var reader = await command.ExecuteAsync()) 
       if(await reader.ReadAsync()) 
        onExecute(reader); 
     }); 
    } 
} 

和閱讀:

await executor.ExecuteAsync(query, async reader => 
{ 
    do 
    { 
     products.Add(GetProduct(reader)); 
     columnValues.Enqueue(GetColumnValues(reader).ToList()); 
    } while(await reader.ReadAsync()); 
}, parameters.ToArray()); 

await reader.ReadAsync()返回true,但當GetProduct(reader)呼叫reader.GetInt32(0);第32屆的時候,它會拋出異常。

它工作正常,如果數據少於32行,或者在SequentialAccess的情況下爲265。 我試圖增加CommandTimeout,但它沒有幫助。當我再次將連接交換到OleDb時,它工作得很好。

在此先感謝。


編輯

如果我只有幾個特定的​​列查詢替換*,它的工作原理。當我讀到〜12列時,它失敗了,但晚於第32行。

根據要求,GetProduct:

private Product GetProduct(IDataReader productReader) 
{ 
    return new Product 
    { 
     Id = productReader.ReadLong(0), 
     Number = productReader.ReadString(2), 
     EanNo = productReader.ReadString(3), 
     Frequency = productReader.ReadInt(4), 
     Status = productReader.ReadInt(5), 
     NameId = productReader.ReadLong(6), 
     KMPI = productReader.ReadByte(7), 
     OEM = productReader.ReadString(8), 
     CurvesetId = productReader.ReadInt(9), 
     HasServiceInfo = Convert.ToBoolean(productReader.ReadByte(10)), 
     ColumnData = new List<ColumnData>() 
    }; 
} 

GetColumnData:

private IEnumerable<long> GetColumnValues(IDataReader productReader) 
{ 
    var columnValues = new List<long>(); 
    int columnIndex = 11; 
    while(!productReader.IsNull(columnIndex)) 
     columnValues.Add(productReader.ReadLong(columnIndex++)); 
    return columnValues; 
} 

和適配器:

public long ReadLong(int columnIndex) 
{ 
    return reader.GetInt32(columnIndex); 
} 

正常的,這也越來越長。 :) 感謝@Igor,我試着創建一個小的工作示例。這似乎很好地工作:

private static async Task Run() 
    { 
     var result = new List<Product>(); 
     string conString = @" ... "; 
     var con = new SqlConnection(conString); 
     con.Open(); 
     using(var command = new SqlCommand("SELECT * FROM Products2 WHERE Products2.PgId = @p;", con)) 
     { 
      command.Parameters.Add(new SqlParameter("p", 337)); 
      await Task.Run(async() => 
      { 
       using(var productReader = await command.ExecuteReaderAsync()) 
        while(await productReader.ReadAsync()) 
        { 
         result.Add(new Product 
         { 
          Id = productReader.GetInt32(0), 
          Number = productReader.GetString(2), 
          EanNo = productReader.GetString(3), 
          Frequency = productReader.GetInt16(4), 
          Status = productReader.GetInt16(5), 
          NameId = productReader.GetInt32(6), 
          KMPI = productReader.GetByte(7), 
          OEM = productReader.GetString(8), 
          CurvesetId = productReader.GetInt16(9), 
          HasServiceInfo = Convert.ToBoolean(productReader.GetByte(10)) 
         }); 
         GetColumnValues(productReader); 
        } 
      }); 
     } 
     Console.WriteLine("End"); 
    } 
    private static IEnumerable<long> GetColumnValues(SqlDataReader productReader) 
    { 
     var columnValues = new List<long>(); 
     int columnIndex = 11; 
     while(!productReader.IsDBNull(columnIndex)) 
      columnValues.Add(productReader.GetInt32(columnIndex++)); 
     return columnValues; 
    } 
} 

下面是訪問數據,以防萬一:

enter image description here

+0

不要這樣做異步,你的問題可能會消失。 – Ben

+0

@BensaysNotoPoliticsonSO,你如何建議我保持敏感呢? –

+0

通過正確索引它使查詢很快。 – Ben

回答

0

我設法解決這個問題。

雖然我仍然有疑問,因爲我不明白爲什麼這不會影響Access。

我改變:

public async Task ExecuteAsync(string query, Action<IDataReader> onExecute, params DataParameter[] parameters) 
{ 
    using(var command = builder.BuildCommand(query)) 
    { 
     foreach(var parameter in parameters) 
      command.AddParameter(parameter); 
     if(!connection.IsOpen) 
      connection.Open(); 
     await Task.Run(async() => 
     { 
      using(var reader = await command.ExecuteAsync()) 
       if(await reader.ReadAsync()) 
        onExecute(reader); 
     }); 
    } 
} 

要:

public async Task ExecuteAsync(string query, Func<IDataReader, Task> onExecute, params DataParameter[] parameters) 
{ 
    using(var command = builder.BuildCommand(query)) 
    { 
     foreach(var parameter in parameters) 
      command.AddParameter(parameter); 
     if(!connection.IsOpen) 
      connection.Open(); 
     using(var reader = await command.ExecuteAsync()) 
      await onExecute(reader); 
    } 
} 

如果有人可以解釋爲什麼這幫助了,我真的很感激它。

相關問題