2017-07-19 94 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); 
    } 
} 

如果有人可以解释为什么这帮助了,我真的很感激它。

相关问题