gpt4 book ai didi

c# - ExecuteReaderAsync 和 Autofac

转载 作者:行者123 更新时间:2023-11-30 16:46:06 27 4
gpt4 key购买 nike

我创建了一个 OracleUnitOfWorkRepository 类,如下所示:

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 方法执行此操作,因为它将不再是异步的,而我需要它是。

有谁知道如何解决这个问题?

最佳答案

For most queries, this is fine, but I seem to have a problem when trying to execute multiple queries simultaneously.

你有一个竞争条件,你试图跨多个线程访问相同的引用并获得“怪异”的行为。

你不能像那样在多个线程之间传递可变单例,它会中断。要么硬着头皮用一个_lock或重新考虑您的方法(即不要使用单例)。

请记住,如果使用不当,锁会破坏您的多线程性能。

关于c# - ExecuteReaderAsync 和 Autofac,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41020833/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com