InvalidOperationException: невозможно разрешить службу для типа «DataAccessContext» при попытке активировать «UnitOfWork» - PullRequest
0 голосов
/ 03 февраля 2020

Я получаю сообщение об ошибке ниже. Я использую. Net Core web API.

Произошло необработанное исключение при обработке запроса. InvalidOperationException: невозможно разрешить службу для типа «CustomerManager.Db.DataAccessContext» при попытке активировать «CustomerManager.Repository.UnitOfWork». Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites (Тип serviceType, Тип реализации TypeType, CallSiteChain callSiteChain, ParameterInfo [], параметры bool throwIfCallSiteNotFound)

1005

1008 1010 *

Модель клиента

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;
            });

        }
    }

Generi c Интерфейс репозитория

public interface IRepository<TEntity> where TEntity : class
    {
        Task<List<TEntity>> GetAllAsync();
    }

Generi c Реализация репозитория

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>();
        }

Как решить эту проблему?

Ответы [ 3 ]

1 голос
/ 04 февраля 2020

Произошло необработанное исключение при обработке запроса. InvalidOperationException: невозможно разрешить службу для типа «CustomerManager.Db.DataAccessContext» при попытке активировать «CustomerManager.Repository.UnitOfWork».

Это потому, что вы не регистрируетесь DataAccessContext в Startup.cs .

Поскольку ваше DataAccessContext равно abstract, обратите внимание, что вы, как правило, не можете зарегистрировать абстрактные классы, поскольку их нельзя создавать.

Измените, как показано ниже:

public class DataAccessContext {}

Зарегистрируйтесь, как показано ниже:

services.AddScoped(typeof(DataAccessContext));
0 голосов
/ 04 февраля 2020

services.AddScoped лучше, чем AddSingleton для этого решения

0 голосов
/ 03 февраля 2020

Ничто в показанных фрагментах кода не демонстрирует, почему DataAccessContext должен быть abstract классом.

Сделать его конкретным классом

public class DataAccessContext {
    //...code omitted for brevity
}

Во-вторых, классы должны зависеть от абстракций услуги, а не конкреции. 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
}

В этом случае зависимые классы должны явно зависеть от этой абстракции

Например

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>();

, чтобы он знал, как разрешить службу при активации ее зависимых

...