我已經創建了一個OracleUnitOfWork和庫類是這樣的:ExecuteReaderAsync和Autofac
public class OracleUnitOfWork : IOracleUnitOfWork
{
// Private properties
private readonly OracleConnection _connection;
private readonly OracleCommand _command;
private readonly Dictionary<Type, object> _repositories;
private Object thisLock = new Object();
/// <summary>
/// Default constructor
/// </summary>
/// <param name="config">The Cormar config class</param>
public OracleUnitOfWork(CormarConfig config)
{
// Create instances for our private properties
this._repositories = new Dictionary<Type, object>();
this._connection = new OracleConnection(config.ConnectionString);
this._command = new OracleCommand
{
Connection = this._connection,
CommandType = CommandType.StoredProcedure,
BindByName = true
};
// Open our connection
this._connection.Open();
}
/// <summary>
/// Gets the entity repository
/// </summary>
/// <typeparam name="T">The entity model</typeparam>
/// <returns></returns>
public IRepository<T> GetRepository<T>() where T : class, new()
{
// Lock the thread so we can't execute at the same time
lock (thisLock)
{
// If our repositories have a matching repository, return it
if (_repositories.Keys.Contains(typeof(T)))
return _repositories[typeof(T)] as IRepository<T>;
// Create a new repository for our entity
var repository = new Repository<T>(this._command);
// Add to our list of repositories
_repositories.Add(typeof(T), repository);
// Return our repository
return repository;
}
}
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes of any attached resources
/// </summary>
/// <param name="disposing">A boolean indicating whether the object is being disposed</param>
protected virtual void Dispose(bool disposing)
{
// If we are disposing
if (disposing)
{
// Close our connection
this._connection.Close();
this._connection.Dispose();
this._command.Dispose();
}
}
}
public class Repository<T> : IRepository<T> where T : class, new()
{
// private properties
private readonly OracleCommand _command;
private Object thisLock = new Object();
/// <summary>
/// Default constructor
/// </summary>
/// <param name="command"></param>
public Repository(OracleCommand command)
{
this._command = command;
}
/// <summary>
/// Returns the datareader for the stored procedure
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">The parameters needed for the SPROC</param>
/// <returns></returns>
public async Task<IDataReader> ExecuteReaderAsync(string storedProcedureName, IList<OracleParameter> parameters = null)
{
// Set up our command
this.InitiateCommand(storedProcedureName, parameters.ToArray());
// Return our data reader
return await this._command.ExecuteReaderAsync();
}
/// <summary>
/// Create, updates or deletes an entity
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">The parameters needed for the SPROC</param>
public async Task CreateUpdateOrDeleteAsync(string storedProcedureName, IList<OracleParameter> parameters = null)
{
// Set up our command
this.InitiateCommand(storedProcedureName, parameters.ToArray());
// Execute our command
await this._command.ExecuteNonQueryAsync();
}
/// <summary>
/// Intiates the command object
/// </summary>
/// <param name="storedProcedureName">The name of the SPROC to execute</param>
/// <param name="parameters">An array of parameters</param>
private void InitiateCommand(string storedProcedureName, OracleParameter[] parameters)
{
// Lock the thread so we can't execute at the same time
lock (thisLock)
{
// Set up the command object
this._command.CommandTimeout = 1800;
this._command.FetchSize = 1000;
this._command.CommandText = storedProcedureName;
this._command.Parameters.Clear();
// If we have any parameters
if (parameters != null)
{
// Assign each parameter to the command object
this._command.Parameters.AddRange(parameters);
}
}
}
}
在我AutoFac模塊,我註冊OracleUnitOfWork作爲單個實例是這樣的:
builder.RegisterType<OracleUnitOfWork>().As<IOracleUnitOfWork>().SingleInstance();
對於大多數查詢,這是好的,但我似乎有一個問題,當試圖同時執行多個查詢。它的錯誤出在ExecuteReaderAsync方法在我的倉庫,並指出:
Object reference not set to an instance of an object.
有時我甚至得到這個錯誤:
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
但我無法弄清楚如何解決這個問題。 在此之前,我得到的問題與GetRepository方法,但是當我添加鎖定,解決了問題。我不能這樣做到ExecuteReaderAsync方法,因爲它不再是異步的,我需要它。
有誰知道如何解決這個問題?