InvalidOperationException:尝试激活 'UnitOfWork' 时无法解析类型 'DataAccessContext' 的服务
InvalidOperationException: Unable to resolve service for type 'DataAccessContext' while attempting to activate 'UnitOfWork'
我收到以下错误。我正在使用 .Net Core 网络 API.
An unhandled exception occurred while processing the request.
InvalidOperationException: Unable to resolve service for type 'CustomerManager.Db.DataAccessContext' while attempting to activate 'CustomerManager.Repository.UnitOfWork'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
Api控制器
[Route("api/[controller]")]
[ApiController]
public class CustomerController : ControllerBase
{
private ICustomersManager _customersManager = null;
public CustomerController(ICustomersManager customersManager)
{
_customersManager = customersManager;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var customers = await _customersManager.GetAll();
return Ok(customers);
}
}
客户模型
public class Customers
{
public Customers()
{
Customers customer = this;
customer.CustomerBankDetails = new List<CustomerBankDetail>();
customer.CustomerContactDetails = new List<CustomerContactDetail>();
customer.CustomerFamilyDetails = new List<CustomerFamilyDetail>();
customer.CustomerPhotos = new List<CustomerPhoto>();
}
public int Id { get; set; }
public string CustomerNo { get; set; }
public string CustomerName { get; set; }
public string Gender { get; set; }
public DateTime? CustomerEntryDate { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Nationality { get; set; }
public bool? IsApproved { get; set; }
public bool IsActive { get; set; }
public bool? IsDeleted { get; set; }
public byte? SortedBy { get; set; }
public string Remarks { get; set; }
public virtual IEnumerable<CustomerBankDetail> CustomerBankDetails { get; set; }
public virtual IEnumerable<CustomerContactDetail> CustomerContactDetails { get; set; }
public virtual IEnumerable<CustomerFamilyDetail> CustomerFamilyDetails { get; set; }
public virtual IEnumerable<CustomerPhoto> CustomerPhotos { get; set; }
}
客户业务层代码
public interface ICustomersManager
{
Task<List<Customers>> GetAll();
}
BLL 实现
public class CustomersManager : ICustomersManager
{
private IUnitOfWork _unitOfWork = null;
public CustomersManager(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public async Task<List<Customers>> GetAll()
{
return await _unitOfWork.CustomerRepository.GetAllAsync();
}
}
工作单元接口
public interface IUnitOfWork : IDisposable
{
ICustomerRepository CustomerRepository { get; }
}
工作单元实现
public class UnitOfWork : IUnitOfWork
{
#region properties
private readonly DataAccessContext _context;
private ICustomerRepository _customerRepository;
public UnitOfWork(DataAccessContext context)
{
_context = context;
}
#endregion
public ICustomerRepository CustomerRepository =>
_customerRepository ?? (_customerRepository = new CustomerRepository(_context));
public void Dispose()
{
_customerRepository = null;
}
}
客户存储库界面
public interface ICustomerRepository : IRepository<Customers>
{
}
客户存储库实施
public class CustomerRepository : BaseRepository, ICustomerRepository
{
public CustomerRepository(DataAccessContext objDataAccessContext) : base(objDataAccessContext)
{
}
public Task<List<Customers>> GetAllAsync()
{
return Task.Run(() =>
{
var objCustomerList = new List<Customers>();
ObjDbCommand.Parameters.Clear();
ObjDbCommand.AddInParameter("@Id", null);
try
{
ObjDbDataReader = ObjDataAccessContext.ExecuteReader(ObjDbCommand, "dbo.prGetAllCustomers", CommandType.StoredProcedure);
if (ObjDbDataReader.HasRows)
while (ObjDbDataReader.Read())
{
var objCustomer = new Customers();
BuildModel(ObjDbDataReader, objCustomer);
objCustomerList.Add(objCustomer);
}
}
catch (Exception ex)
{
throw new Exception("Error : " + ex.Message);
}
finally
{
if (ObjDbDataReader != null) ObjDbDataReader.Close();
ObjDataAccessContext.Dispose(ObjDbCommand);
}
return objCustomerList;
});
}
}
通用存储库界面
public interface IRepository<TEntity> where TEntity : class
{
Task<List<TEntity>> GetAllAsync();
}
通用存储库实现
public class BaseRepository
{
protected readonly DataAccessContext ObjDataAccessContext;
protected readonly DbCommand ObjDbCommand;
protected DbDataReader ObjDbDataReader;
protected BaseRepository(DataAccessContext objDataAccessContext)
{
ObjDataAccessContext = objDataAccessContext;
ObjDbCommand = ObjDataAccessContext.GetCommand(true, IsolationLevel.ReadCommitted);
}
protected void BuildModel<T>(DbDataReader objDataReader, T item) where T : class
{
for (var inc = 0; inc < objDataReader.FieldCount; inc++)
{
var type = item.GetType();
var prop = type.GetProperty(objDataReader.GetName(inc));
var val = objDataReader.GetValue(inc) is DBNull || objDataReader.GetValue(inc).Equals(null) ||
string.IsNullOrEmpty(Convert.ToString(objDataReader.GetValue(inc)))
? null
: objDataReader.GetValue(inc);
prop?.SetValue(item, val, null);
}
}
}
数据库访问上下文使用 ADO.NET
public abstract class DataAccessContext
{
public DbCommand GetCommand(bool isTransaction, IsolationLevel isolationLevel)
{
var connectionString = DbConfiguration.ConnectionString;
return GetDbCommand(isTransaction, isolationLevel, connectionString);
}
public int ExecuteNonQuery(DbCommand objDbCommand, string textOrSpName, CommandType commandType)
{
try
{
objDbCommand.CommandType = commandType;
objDbCommand.CommandText = textOrSpName;
return objDbCommand.ExecuteNonQuery();
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteNonQuery " + textOrSpName, sqlEx);
}
}
public int ExecuteNonQuery(DbCommand objDbCommand)
{
try
{
return objDbCommand.ExecuteNonQuery();
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteNonQuery " + objDbCommand.CommandText, sqlEx);
}
}
public DbDataReader ExecuteReader(DbCommand objDbCommand, string textOrSpName, CommandType commandType)
{
try
{
objDbCommand.CommandType = commandType;
objDbCommand.CommandText = textOrSpName;
return objDbCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteReader " + textOrSpName, sqlEx);
}
}
public DbDataReader ExecuteReader(DbCommand objDbCommand)
{
try
{
return objDbCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteReader " + objDbCommand.CommandText, sqlEx);
}
}
public void Dispose(DbCommand objDbCommand)
{
if (objDbCommand.Connection != null)
{
objDbCommand.Connection.Dispose();
objDbCommand.Connection = null;
}
if (objDbCommand.Transaction != null)
{
objDbCommand.Transaction.Dispose();
objDbCommand.Transaction = null;
}
objDbCommand.Dispose();
objDbCommand = null;
}
private DbCommand GetDbCommand(bool bIsTransaction, IsolationLevel isolationLevel, string connectionString)
{
// retrieve provider invariant name from web.config
var providerInvariantName = string.Empty;
if (string.IsNullOrEmpty(providerInvariantName))
providerInvariantName = "System.Data.SqlClient";
// create the specific invariant provider
//DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance);
var objDbProviderFactory = DbProviderFactories.GetFactory(providerInvariantName);
var objDbConnection = objDbProviderFactory.CreateConnection();
if (objDbConnection == null) return null;
objDbConnection.ConnectionString = connectionString;
var objDbCommand = objDbProviderFactory.CreateCommand();
if (objDbCommand == null) return null;
objDbCommand.Connection = objDbConnection;
objDbConnection.Open();
if (bIsTransaction)
{
var objDbTransaction = objDbConnection.BeginTransaction(isolationLevel);
objDbCommand.Transaction = objDbTransaction;
return objDbCommand;
}
return objDbCommand;
}
}
这是Startup.cs文件
public void ConfigureServices(IServiceCollection services)
{
DbConfiguration.ServerName = Configuration["DbConnection:ServerName"];
DbConfiguration.DatabaseName = Configuration["DbConnection:DatabaseName"];
DbConfiguration.UserId = Configuration["DbConnection:UserId"];
DbConfiguration.Password = Configuration["DbConnection:Password"];
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//services.AddSingleton(typeof(DataAccessContext));
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
//Dependency Injection
//services.AddScoped(sp => sp.GetService(typeof(DataAccessContext)));
services.AddScoped<ICustomerRepository, CustomerRepository>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped<ICustomersManager, CustomersManager>();
}
如何解决这个问题?
显示的代码片段中没有任何内容可以说明为什么 DataAccessContext
应该是 abstract
class。
具体化class
public class DataAccessContext {
//...code omitted for brevity
}
其次,classes 应该依赖于服务的抽象而不是具体化。 DataAccessContext
应该有一个支持抽象。
public interface IDataAccessContext {
DbCommand GetCommand(bool isTransaction, IsolationLevel isolationLevel);
int ExecuteNonQuery(DbCommand objDbCommand, string textOrSpName, CommandType commandType);
int ExecuteNonQuery(DbCommand objDbCommand);
DbDataReader ExecuteReader(DbCommand objDbCommand, string textOrSpName, CommandType commandType);
DbDataReader ExecuteReader(DbCommand objDbCommand);
Dispose(DbCommand objDbCommand);
//...
}
和
public class DataAccessContext: IDataAccessContext {
//...code omitted for brevity
}
Dependent classes 应该显式依赖于那个抽象
例如
public class UnitOfWork : IUnitOfWork {
private readonly IDataAccessContext _context;
private ICustomerRepository _customerRepository;
public UnitOfWork(IDataAccessContext context) {
_context = context;
}
//...omitted for brevity
以及向DI容器注册的抽象和实现
services.AddSingleton<IDataAccessContext, DataAccessContext>();
以便它知道如何在激活其依赖项时解析服务
An unhandled exception occurred while processing the request.
InvalidOperationException: Unable to resolve service for type
'CustomerManager.Db.DataAccessContext' while attempting to activate
'CustomerManager.Repository.UnitOfWork'.
那是因为你没有在Startup.cs中注册DataAccessContext
。
因为你的DataAccessContext
是abstract
,注意你一般不能注册抽象类,因为它们不能被实例化。
更改如下:
public class DataAccessContext {}
按如下方式注册:
services.AddScoped(typeof(DataAccessContext));
services.AddScoped 在这个问题上比 AddSingleton 更好
我收到以下错误。我正在使用 .Net Core 网络 API.
An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'CustomerManager.Db.DataAccessContext' while attempting to activate 'CustomerManager.Repository.UnitOfWork'. Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
Api控制器
[Route("api/[controller]")]
[ApiController]
public class CustomerController : ControllerBase
{
private ICustomersManager _customersManager = null;
public CustomerController(ICustomersManager customersManager)
{
_customersManager = customersManager;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var customers = await _customersManager.GetAll();
return Ok(customers);
}
}
客户模型
public class Customers
{
public Customers()
{
Customers customer = this;
customer.CustomerBankDetails = new List<CustomerBankDetail>();
customer.CustomerContactDetails = new List<CustomerContactDetail>();
customer.CustomerFamilyDetails = new List<CustomerFamilyDetail>();
customer.CustomerPhotos = new List<CustomerPhoto>();
}
public int Id { get; set; }
public string CustomerNo { get; set; }
public string CustomerName { get; set; }
public string Gender { get; set; }
public DateTime? CustomerEntryDate { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Nationality { get; set; }
public bool? IsApproved { get; set; }
public bool IsActive { get; set; }
public bool? IsDeleted { get; set; }
public byte? SortedBy { get; set; }
public string Remarks { get; set; }
public virtual IEnumerable<CustomerBankDetail> CustomerBankDetails { get; set; }
public virtual IEnumerable<CustomerContactDetail> CustomerContactDetails { get; set; }
public virtual IEnumerable<CustomerFamilyDetail> CustomerFamilyDetails { get; set; }
public virtual IEnumerable<CustomerPhoto> CustomerPhotos { get; set; }
}
客户业务层代码
public interface ICustomersManager
{
Task<List<Customers>> GetAll();
}
BLL 实现
public class CustomersManager : ICustomersManager
{
private IUnitOfWork _unitOfWork = null;
public CustomersManager(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public async Task<List<Customers>> GetAll()
{
return await _unitOfWork.CustomerRepository.GetAllAsync();
}
}
工作单元接口
public interface IUnitOfWork : IDisposable
{
ICustomerRepository CustomerRepository { get; }
}
工作单元实现
public class UnitOfWork : IUnitOfWork
{
#region properties
private readonly DataAccessContext _context;
private ICustomerRepository _customerRepository;
public UnitOfWork(DataAccessContext context)
{
_context = context;
}
#endregion
public ICustomerRepository CustomerRepository =>
_customerRepository ?? (_customerRepository = new CustomerRepository(_context));
public void Dispose()
{
_customerRepository = null;
}
}
客户存储库界面
public interface ICustomerRepository : IRepository<Customers>
{
}
客户存储库实施
public class CustomerRepository : BaseRepository, ICustomerRepository
{
public CustomerRepository(DataAccessContext objDataAccessContext) : base(objDataAccessContext)
{
}
public Task<List<Customers>> GetAllAsync()
{
return Task.Run(() =>
{
var objCustomerList = new List<Customers>();
ObjDbCommand.Parameters.Clear();
ObjDbCommand.AddInParameter("@Id", null);
try
{
ObjDbDataReader = ObjDataAccessContext.ExecuteReader(ObjDbCommand, "dbo.prGetAllCustomers", CommandType.StoredProcedure);
if (ObjDbDataReader.HasRows)
while (ObjDbDataReader.Read())
{
var objCustomer = new Customers();
BuildModel(ObjDbDataReader, objCustomer);
objCustomerList.Add(objCustomer);
}
}
catch (Exception ex)
{
throw new Exception("Error : " + ex.Message);
}
finally
{
if (ObjDbDataReader != null) ObjDbDataReader.Close();
ObjDataAccessContext.Dispose(ObjDbCommand);
}
return objCustomerList;
});
}
}
通用存储库界面
public interface IRepository<TEntity> where TEntity : class
{
Task<List<TEntity>> GetAllAsync();
}
通用存储库实现
public class BaseRepository
{
protected readonly DataAccessContext ObjDataAccessContext;
protected readonly DbCommand ObjDbCommand;
protected DbDataReader ObjDbDataReader;
protected BaseRepository(DataAccessContext objDataAccessContext)
{
ObjDataAccessContext = objDataAccessContext;
ObjDbCommand = ObjDataAccessContext.GetCommand(true, IsolationLevel.ReadCommitted);
}
protected void BuildModel<T>(DbDataReader objDataReader, T item) where T : class
{
for (var inc = 0; inc < objDataReader.FieldCount; inc++)
{
var type = item.GetType();
var prop = type.GetProperty(objDataReader.GetName(inc));
var val = objDataReader.GetValue(inc) is DBNull || objDataReader.GetValue(inc).Equals(null) ||
string.IsNullOrEmpty(Convert.ToString(objDataReader.GetValue(inc)))
? null
: objDataReader.GetValue(inc);
prop?.SetValue(item, val, null);
}
}
}
数据库访问上下文使用 ADO.NET
public abstract class DataAccessContext
{
public DbCommand GetCommand(bool isTransaction, IsolationLevel isolationLevel)
{
var connectionString = DbConfiguration.ConnectionString;
return GetDbCommand(isTransaction, isolationLevel, connectionString);
}
public int ExecuteNonQuery(DbCommand objDbCommand, string textOrSpName, CommandType commandType)
{
try
{
objDbCommand.CommandType = commandType;
objDbCommand.CommandText = textOrSpName;
return objDbCommand.ExecuteNonQuery();
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteNonQuery " + textOrSpName, sqlEx);
}
}
public int ExecuteNonQuery(DbCommand objDbCommand)
{
try
{
return objDbCommand.ExecuteNonQuery();
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteNonQuery " + objDbCommand.CommandText, sqlEx);
}
}
public DbDataReader ExecuteReader(DbCommand objDbCommand, string textOrSpName, CommandType commandType)
{
try
{
objDbCommand.CommandType = commandType;
objDbCommand.CommandText = textOrSpName;
return objDbCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteReader " + textOrSpName, sqlEx);
}
}
public DbDataReader ExecuteReader(DbCommand objDbCommand)
{
try
{
return objDbCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (DbException sqlEx)
{
throw new Exception("ExecuteReader " + objDbCommand.CommandText, sqlEx);
}
}
public void Dispose(DbCommand objDbCommand)
{
if (objDbCommand.Connection != null)
{
objDbCommand.Connection.Dispose();
objDbCommand.Connection = null;
}
if (objDbCommand.Transaction != null)
{
objDbCommand.Transaction.Dispose();
objDbCommand.Transaction = null;
}
objDbCommand.Dispose();
objDbCommand = null;
}
private DbCommand GetDbCommand(bool bIsTransaction, IsolationLevel isolationLevel, string connectionString)
{
// retrieve provider invariant name from web.config
var providerInvariantName = string.Empty;
if (string.IsNullOrEmpty(providerInvariantName))
providerInvariantName = "System.Data.SqlClient";
// create the specific invariant provider
//DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance);
var objDbProviderFactory = DbProviderFactories.GetFactory(providerInvariantName);
var objDbConnection = objDbProviderFactory.CreateConnection();
if (objDbConnection == null) return null;
objDbConnection.ConnectionString = connectionString;
var objDbCommand = objDbProviderFactory.CreateCommand();
if (objDbCommand == null) return null;
objDbCommand.Connection = objDbConnection;
objDbConnection.Open();
if (bIsTransaction)
{
var objDbTransaction = objDbConnection.BeginTransaction(isolationLevel);
objDbCommand.Transaction = objDbTransaction;
return objDbCommand;
}
return objDbCommand;
}
}
这是Startup.cs文件
public void ConfigureServices(IServiceCollection services)
{
DbConfiguration.ServerName = Configuration["DbConnection:ServerName"];
DbConfiguration.DatabaseName = Configuration["DbConnection:DatabaseName"];
DbConfiguration.UserId = Configuration["DbConnection:UserId"];
DbConfiguration.Password = Configuration["DbConnection:Password"];
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//services.AddSingleton(typeof(DataAccessContext));
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
//Dependency Injection
//services.AddScoped(sp => sp.GetService(typeof(DataAccessContext)));
services.AddScoped<ICustomerRepository, CustomerRepository>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped<ICustomersManager, CustomersManager>();
}
如何解决这个问题?
显示的代码片段中没有任何内容可以说明为什么 DataAccessContext
应该是 abstract
class。
具体化class
public class DataAccessContext {
//...code omitted for brevity
}
其次,classes 应该依赖于服务的抽象而不是具体化。 DataAccessContext
应该有一个支持抽象。
public interface IDataAccessContext {
DbCommand GetCommand(bool isTransaction, IsolationLevel isolationLevel);
int ExecuteNonQuery(DbCommand objDbCommand, string textOrSpName, CommandType commandType);
int ExecuteNonQuery(DbCommand objDbCommand);
DbDataReader ExecuteReader(DbCommand objDbCommand, string textOrSpName, CommandType commandType);
DbDataReader ExecuteReader(DbCommand objDbCommand);
Dispose(DbCommand objDbCommand);
//...
}
和
public class DataAccessContext: IDataAccessContext {
//...code omitted for brevity
}
Dependent classes 应该显式依赖于那个抽象
例如
public class UnitOfWork : IUnitOfWork {
private readonly IDataAccessContext _context;
private ICustomerRepository _customerRepository;
public UnitOfWork(IDataAccessContext context) {
_context = context;
}
//...omitted for brevity
以及向DI容器注册的抽象和实现
services.AddSingleton<IDataAccessContext, DataAccessContext>();
以便它知道如何在激活其依赖项时解析服务
An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'CustomerManager.Db.DataAccessContext' while attempting to activate 'CustomerManager.Repository.UnitOfWork'.
那是因为你没有在Startup.cs中注册DataAccessContext
。
因为你的DataAccessContext
是abstract
,注意你一般不能注册抽象类,因为它们不能被实例化。
更改如下:
public class DataAccessContext {}
按如下方式注册:
services.AddScoped(typeof(DataAccessContext));
services.AddScoped 在这个问题上比 AddSingleton 更好