Ошибка конструктора без параметров в ASP.Net Веб-API 2

#entity-framework-6 #asp.net-web-api2 #repository-pattern

#entity-framework-6 #asp.net-web-api2 #репозиторий-шаблон

Вопрос:

Я пытаюсь создать RESTful API, следуя шаблону репозитория. Когда я нажимаю на свой API с помощью postman, я вижу ошибку конструктора без параметров. На самом деле я не могу понять, в чем я ошибаюсь. Скриншот ошибки Я использую первый подход к базе данных EntityFramework6. Я поделился всеми соответствующими примерами кода. Вот мои SSDBEntities.cs

     public partial class SSDBEntities : DbContext
    {
     public SSDBEntities()
        : base("name=SSDBEntities")
      {
      }

     protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
        throw new UnintentionalCodeFirstException();
      }

     public virtual DbSet<Employee> Employees { get; set; }
     public virtual DbSet<Product> Products { get; set; }
}
  

ProductController.cs

 [RoutePrefix("api/ss/products")]
public class ProductController : ApiController
{
    private readonly IProductService _productService;
    public ProductController(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet]
    [Route("get-products")]
    public async Task<IHttpActionResult> GetProducts()
    {
        int total = 0;
        List<ProductModel> model = _productService.getProducts();
        return Ok(new ResponseMessage<List<ProductModel>>()
        {
            Result = model
        });
    }
}
  

IProductService.cs

     public interface IProductService
    {
       List<ProductModel> getProducts();
    }
  

ProductService.cs

     public class ProductService : IProductService
    {
      private readonly ISSRepository<Product> _productRepository;
      public ProductService(ISSRepository<Product> productRepository)
      {
        _productRepository = productRepository;
      }
      public List<ProductModel> getProducts()
      {
        List<Product> products = _productRepository.Where(x => x.IsActive == true).ToList();
        List<ProductModel> models = ObjectConverter<Product, ProductModel>.ConvertList(products).ToList();
        return models;
      }
     }
  

ISSRepository.cs

     public interface ISSRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
      DataTable ExecWithStoreProcedure(string query, IDictionary<string, object> values);
      DataTable ExecWithSqlQuery(string query);
      int ExecNoneQuery(string query);
    }
  

IRepository.cs

 public interface IRepository<T> where T : class
{
    T FindOne(Expression<Func<T, bool>> predicate);

    T FindOne(Expression<Func<T, bool>> predicate, List<string> includeProperties);

    bool Exists(Expression<Func<T, bool>> predicate);

    IQueryable<T> AsQueryable();

    IQueryable<T> Where(Expression<Func<T, bool>> predicate);

    int Count();

    int Count(Expression<Func<T, bool>> predicate);

    int Save(T entity);

    void Insert(T entity);

    int SaveAll(List<T> entity);
    int UpdateAll(List<T> entities);
    int Recreate(List<T> entity);

    int Recreate(List<T> oldEntities, List<T> newEntities);

    int SaveChanges();

    bool Delete(T entity);

    int Delete(Expression<Func<T, bool>> predicate);

    /// <summary>
    /// Add entity to DbSet
    /// </summary>
    /// <param name="entity">Entity to add in DbSet</param>
    void Add(T entity);

    /// <summary>
    /// Add entity collection to DbSet.
    /// </summary>
    /// <param name="entities"></param>
    void AddRange(IEnumerable<T> entities);

    void Remove(T entity);
    int RemoveRange(IEnumerable<T> entities);
    void BlukInsert(IEnumerable<T> entities);
    T FinedOneInclude(Expression<Func<T, bool>> predicate, params string[] include);
    IQueryable<T> FilterWithInclude(Expression<Func<T, bool>> predicate, params string[] include);
    Task<int> SaveAsync(T entity);
    Task<bool> DeleteAsync(T entity);
    Task<bool> DeleteAsync(Expression<Func<T, bool>> predicate);
    Task<int> CountAsync();
    Task<int> SaveAllAsync(List<T> entity);
    Task<int> CountAsync(Expression<Func<T, bool>> predicate);
    Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate);
    Task<T> FindOneAsync(Expression<Func<T, bool>> predicate);
    Task<T> FindOneAsync(Expression<Func<T, bool>> predicate, List<string> includeProperties);
    Task<ICollection<T>> FilterAsync(Expression<Func<T, bool>> predicate);
    Task<int> SaveChangeAsync();
 }
  

Repository.cs

 public abstract class Repository<TDbContext, TEntity> : IRepository<TEntity>
    where TEntity : class
     where TDbContext : DbContext
{
    public readonly TDbContext context;
    private readonly DbSet<TEntity> dbSet;

    protected Repository(TDbContext context)
    {
        this.context = context;
        dbSet = this.context.Set<TEntity>();
        context.Configuration.LazyLoadingEnabled = false;
        context.Configuration.ProxyCreationEnabled = false;
    }

    /// <summary>
    /// Find entity based on lamda-expression
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public virtual TEntity FindOne(Expression<Func<TEntity, bool>> predicate)
    {
        return dbSet.FirstOrDefault(predicate);
    }

    public virtual TEntity FindOne(Expression<Func<TEntity, bool>> predicate, List<string> includeProperties)
    {
        IQueryable<TEntity> query = dbSet.Where(predicate);

        if (includeProperties != null)
        {
            foreach (var name in includeProperties)
            {
                query = query.Include(name);
            }
        }

        return query.FirstOrDefault();
    }

    /// <summary>
    /// Check entity exists or not based on lamda-expression
    /// </summary>
    /// <param name="predicate">Expression to match</param>
    /// <returns></returns>
    public virtual bool Exists(Expression<Func<TEntity, bool>> predicate)
    {
        return dbSet.Any(predicate);
    }

    public virtual IQueryable<TEntity> AsQueryable()
    {
        return dbSet.AsQueryable();
    }

    /// <summary>
    /// Filters a sequence of values based on a predicate.
    /// </summary>
    /// <param name="predicate">A function to test each element for a condition.</param>
    /// <returns>An System.Linq.IQueryable`1 that contains elements from the input sequence that 
    /// satisfy the condition specified by predicate.
    /// </returns>
    public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> predicate)
    {
        return dbSet.Where(predicate);
    }

    public virtual int Count()
    {
        return dbSet.Count();
    }

    public virtual int Count(Expression<Func<TEntity, bool>> predicate)
    {
        return dbSet.Count(predicate);
    }

    public virtual int Save(TEntity entity)
    {
        DbEntityEntry<TEntity> entry = context.Entry(entity);

        if (entry.State == EntityState.Detached)
        {
            dbSet.Add(entity);
            entry.State = EntityState.Added;
        }
        else
        {
            dbSet.Attach(entity);
            entry.State = EntityState.Modified;
        }

        try
        {
            return context.SaveChanges();
        }
        catch
        {
            ClearEntityState();
            throw;
        }
    }

    public virtual void Insert(TEntity entity)
    {
        dbSet.Add(entity);
        SaveChanges();
    }

    public virtual int SaveAll(List<TEntity> entity)
    {
        dbSet.AddRange(entity);
        return SaveChanges();
    }

    public virtual int UpdateAll(List<TEntity> entities)
    {
        foreach (TEntity entity in entities)
        {
            DbEntityEntry<TEntity> entry = context.Entry(entity);

            dbSet.Attach(entity);
            entry.State = EntityState.Modified;
        }
        return SaveChanges();
    }

    public virtual int Recreate(List<TEntity> entity)
    {
        DbSet<TEntity> objects = dbSet;
        dbSet.RemoveRange(objects);
        dbSet.AddRange(entity);
        return SaveChanges();
    }

    public virtual int Recreate(List<TEntity> oldEntities, List<TEntity> newEntities)
    {
        dbSet.RemoveRange(oldEntities);
        dbSet.AddRange(newEntities);
        return SaveChanges();
    }

    public virtual bool Delete(TEntity entity)
    {
        dbSet.Remove(entity);
        return SaveChanges() > 0;
    }

    /// <summary>
    /// Will be used for DeleteALL
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public virtual int Delete(Expression<Func<TEntity, bool>> predicate)
    {
        IQueryable<TEntity> objects = Where(predicate);
        dbSet.RemoveRange(objects);
        return SaveChanges();
    }

    /// <summary>
    /// Save all changes in DbContext
    /// </summary>
    /// <returns></returns>
    public int SaveChanges()
    {
        try
        {
            return context.SaveChanges();
        }
        catch
        {
            ClearEntityState();
            throw;
        }
    }

    private void ClearEntityState()
    {
        List<DbEntityEntry> changedEntries = context.ChangeTracker.Entries().Where(x => x.State != EntityState.Unchanged).ToList();

        foreach (var entry in changedEntries.Where(x => x.State == EntityState.Modified))
        {
            entry.CurrentValues.SetValues(entry.OriginalValues);
            entry.State = EntityState.Unchanged;
        }

        foreach (var entry in changedEntries.Where(x => x.State == EntityState.Added))
        {
            entry.State = EntityState.Detached;
        }

        foreach (var entry in changedEntries.Where(x => x.State == EntityState.Deleted))
        {
            entry.State = EntityState.Unchanged;
        }
    }

    /// <summary>
    /// Add entity to DbSet. SaveChanges requires to update database.
    /// </summary>
    /// <param name="entity">Entity to add in DbSet</param>
    public virtual void Add(TEntity entity)
    {
        dbSet.Add(entity);
    }

    /// <summary>
    /// Add entity collection to DbSet. SaveChanges requires to update database.
    /// </summary>
    /// <param name="entities"></param>
    public virtual void AddRange(IEnumerable<TEntity> entities)
    {
        dbSet.AddRange(entities);
    }

    /// <summary>
    /// Remove entity from DbSet. SaveChanges requires to update database.
    /// </summary>
    /// <param name="entity">Entity to remove from DbSet</param>
    public virtual void Remove(TEntity entity)
    {
        dbSet.Remove(entity);
    }


    public virtual void BlukInsert(IEnumerable<TEntity> entities)
    {
        bool autoDetectChangesEnabled = context.Configuration.AutoDetectChangesEnabled;
        bool validateOnSaveEnabled = context.Configuration.ValidateOnSaveEnabled;

        context.Configuration.AutoDetectChangesEnabled = false;
        context.Configuration.ValidateOnSaveEnabled = false;

        dbSet.AddRange(entities);
        SaveChanges();

        context.Configuration.AutoDetectChangesEnabled = autoDetectChangesEnabled;
        context.Configuration.ValidateOnSaveEnabled = validateOnSaveEnabled;
    }

    public virtual IQueryable<TEntity> GetAllInclude(params string[] include)
    {
        IQueryable<TEntity> query = this.dbSet.AsNoTracking();
        query = include.Aggregate(query, (current, inc) => current.Include(inc));
        return query.AsQueryable();
    }

    public virtual TEntity FinedOneInclude(Expression<Func<TEntity, bool>> predicate, params string[] include)
    {
        IQueryable<TEntity> query = this.dbSet.AsNoTracking();
        query = include.Aggregate(query, (current, inc) => current.Include(inc));
        return query.FirstOrDefault(predicate);
    }

    public virtual IQueryable<TEntity> FilterWithInclude(Expression<Func<TEntity, bool>> predicate, params string[] include)
    {
        IQueryable<TEntity> query = this.dbSet.AsNoTracking();
        query = include.Aggregate(query, (current, inc) => current.Include(inc));
        return query.Where(predicate).AsQueryable();
    }

    public virtual Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return dbSet.CountAsync(predicate);
    }

    public virtual Task<int> CountAsync()
    {
        return dbSet.CountAsync();
    }


    public async virtual Task<int> SaveChangeAsync()
    {
        try
        {
            return await context.SaveChangesAsync();
        }
        catch (Exception e)
        {

            ClearEntityState();
            throw;
        }
    }

    public virtual Task<int> SaveAsync(TEntity entity)
    {
        DbEntityEntry<TEntity> entry = context.Entry(entity);

        if (entry.State == EntityState.Detached)
        {
            dbSet.Add(entity);
            entry.State = EntityState.Added;
        }
        else
        {
            dbSet.Attach(entity);
            entry.State = EntityState.Modified;
        }

        try
        {
            return SaveChangeAsync();
        }
        catch
        {
            ClearEntityState();
            throw;
        }
    }

    public virtual Task<TEntity> FindOneAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return dbSet.FirstOrDefaultAsync(predicate);
    }

    public Task<TEntity> FindOneAsync(Expression<Func<TEntity, bool>> predicate, List<string> includeProperties)
    {
        IQueryable<TEntity> query = this.dbSet.AsNoTracking();
        query = includeProperties.Aggregate(query, (current, inc) => current.Include(inc));
        return query.FirstOrDefaultAsync(predicate);
    }


    public virtual Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return dbSet.AnyAsync(predicate);
    }

    public async virtual Task<bool> DeleteAsync(TEntity entity)
    {
        dbSet.Remove(entity);
        try
        {
            var effectedRows = await SaveChangeAsync();
            return effectedRows > 0;
        }
        catch (Exception e)
        {

            throw new Exception("Someting went wrong. Please first delete family information");

        }

    }

    public async virtual Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> predicate)
    {
        IQueryable<TEntity> objects = Where(predicate);
        dbSet.RemoveRange(objects);
        return await SaveChangeAsync() > 0;
    }

    public async virtual Task<ICollection<TEntity>> FilterAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return await dbSet.Where(predicate).ToListAsync();
    }

    public Task<int> SaveAllAsync(List<TEntity> entity)
    {
        dbSet.AddRange(entity);
        return SaveChangeAsync();
    }

    public int RemoveRange(IEnumerable<TEntity> entities)
    {
        dbSet.RemoveRange(entities);
        return SaveChanges();
    }
}
  

SSRepository.cs

 public class SSRepository<T> : Repository<SSDBEntities, T>, ISSRepository<T>
     where T : class
{
    internal SqlConnection Connection;
    public SSRepository(SSDBEntities context) : base(context)
    {
        Connection = context.Database.Connection as SqlConnection;
    }
    public DataTable ExecWithStoreProcedure(string query, IDictionary<string, object> values)
    {

        using (Connection)

        using (SqlCommand cmd = new SqlCommand())
        {
            cmd.CommandText = query;
            foreach (KeyValuePair<string, object> item in values)
            {
                cmd.Parameters.AddWithValue("@"   item.Key, item.Value);
            }
            DataTable table = new DataTable();
            using (var reader = cmd.ExecuteReader())
            {
                table.Load(reader);
                return table;
            }
        }
    }

    public DataTable ExecWithSqlQuery(string query)
    {
        try
        {
            Connection.Open();
            SqlCommand cmd = new SqlCommand(query, Connection);
            DataTable dt = new DataTable();
            SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd);
            dataAdapter.Fill(dt);
            return dt;
        }
        catch
        {
            throw new Exception();
        }
        finally
        {
            if
                (Connection.State == ConnectionState.Open)
            {

                Connection.Close();
            }
        }



    }

    public int ExecNoneQuery(string query)
    {
        try
        {
            Connection.Open();
            using (SqlCommand cmd = new SqlCommand(query, Connection))
            {
                return cmd.ExecuteNonQuery();
            }
        }
        catch
        {
            throw new Exception();
        }
        finally
        {
            if
                (Connection.State == ConnectionState.Open)
            {

                Connection.Close();
            }
        }


    }
}
  

Кто-нибудь может помочь мне решить эту проблему?

Ответ №1:

В этом случае ошибка точно сообщает вам, в чем проблема — у вашего контроллера нет конструктора, который принимает нулевые параметры. например:

 public ProductController()
{
}
  

По умолчанию приложение не знает, как предоставить an IProductService в качестве параметра.
Если вы создаете конструктор по умолчанию, вы можете создать IProductService в нем новый, а не принимать его как параметр или как инициализацию свойства.

Если вы не хотите иметь конструктор без параметров, вы можете использовать некоторую форму внедрения зависимостей, которая была бы настроена так, чтобы знать, как создать IProductService и предоставить его вашему существующему конструктору.

Комментарии:

1. Когда я использую ProductController таким образом, он работает нормально. public ProductController() { _productService = ;new ProductService(); } Я хочу знать, это лучшее решение?

2. Обычно, если вам требуются дополнительные сервисы, подобные этому, в контроллере, вы должны настроить какой-то контейнер для внедрения зависимостей, такой как SimpleInjector или Unity. Однако нет ничего плохого в том, чтобы делать это в конструкторе. Вы всегда можете добавить внедрение зависимостей позже, если сочтете, что это было бы полезно.