Создание универсального контроллера веб-API при использовании нескольких таблиц с похожими полями

Я пытался реорганизовать свой код с тех пор, как обнаружил, что много копирую и вставляю, чтобы реализовать логику контроллеров веб-API. Вот как выглядели контроллеры до рефакторинга

Контроллер для EducationalGroups стол:

public class EducationalGroupsController : ApiController
    {
        public HttpResponseMessage Get()
        {
            try
            {
                using (SchoolDbContext entities = new SchoolDbContext())
                    return Request.CreateResponse(HttpStatusCode.OK,
                        entities.EducationGroups.Where(g => !g.Is_Delete).ToList());
            }
            catch (Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NoContent, e);
            }
        }

        public HttpResponseMessage Post([FromBody] EducationGroup group)
        {
            try
            {
                using (SchoolDbContext entities = new SchoolDbContext())
                {
                    group.Create_User = WebApiConfig.CurrUserIdx;
                    group.Create_Date = DateTime.Now;

                    entities.EducationGroups.Add(group);
                    entities.SaveChanges();

                    var msg = Request.CreateResponse(HttpStatusCode.Created, group);
                    msg.Headers.Location = new Uri(Request.RequestUri, group.Id.ToString());
                    return msg;
                }
            }
            catch (Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, e);
            }
        }
    }

Контроллер для EducationalStages стол:

public class EducationalStagesController : ApiController
    {
        public HttpResponseMessage Get()
        {
            try
            {
                //Notice the only difference here is the *Educational_Stages* object of type DbSet
                using (SchoolDbContext entities = new SchoolDbContext())
                    return Request.CreateResponse(HttpStatusCode.OK, 
                        entities.Education_Stages.Where(s => !s.Is_Delete).ToList());
            }
            catch (Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NoContent, e);
            }
        }

        //Same implementation for this method as previous controller 
        //Only with the difference of the type of the parameter
        public HttpResponseMessage Post([FromBody] Education_Stages stage)
        {
            try
            {
                using (SchoolDbContext entities = new SchoolDbContext())
                {
                    stage.Create_User = WebApiConfig.CurrUserIdx;
                    stage.Create_Date = DateTime.Now;

                    entities.Education_Stages.Add(stage);
                    entities.SaveChanges();

                    var msg = Request.CreateResponse(HttpStatusCode.Created, stage);
                    msg.Headers.Location = new Uri(Request.RequestUri, stage.Id.ToString());
                    return msg;
                }
            }
            catch (Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, e);
            }
        }
    }

Для еще 8 таблиц требуется еще 8 контроллеров, так что вы понимаете, насколько это избыточно …

Я пытался создать базовый класс для сущностей, которые имеют одни и те же поля, как показано ниже:

public abstract class BaseEntity
    {
        public int Id { get; set; }

        [StringLength(50)]
        public string Ar_Name { get; set; }

        [StringLength(10)]
        public string En_Name { get; set; }

        public bool Is_Delete { get; set; }

        public int? Create_User { get; set; }

        public DateTime? Create_Date { get; set; }

        public int? Last_Update_User { get; set; }

        public DateTime? Last_Update_Date { get; set; }
    }

И унаследовать его от всех сущностей, использующих одни и те же поля:

public partial class Education_Stages : BaseEntity
    {
    }

А затем создайте базовый класс для контроллеров API, чтобы наследовать от него, как показано ниже, и вот где я не могу найти больше решений для того, что хочу:

public abstract class BaseApiVerbs<T> : ApiController where T : BaseEntity
    {
        private DbSet<T> dbSet;

        public BaseApiVerbs(DbSet<T> _dbSet)
        {
            dbSet = _dbSet;
        }

        public HttpResponseMessage Get()
        {
            try
            {
                return Request.CreateResponse(HttpStatusCode.OK, 
                    dbSet.Where(t => t.Is_Delete == false));
            }
            catch (Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, e);
            }
        }
        public HttpResponseMessage Post([FromBody] T entity)
        {
            // No Idea how to implement the same logic here without using DbContext... 
        }

Кроме того, я не знаю, как инициализировать классы контроллеров и передать DbSet объект соответственно:

public class CityController : BaseApiVerbs<City>
    {
        SchoolDbContext context = new SchoolDbContext();
        public CityController() 
            : base( /* How would I pass the DbSet object here? */ )
        {
            
        }
    }

Приемлема ли в этом случае идея копирования и вставки кода? Если нет, как я могу выполнить то, что пытался сделать последние два дня?

Я новичок, поэтому, пожалуйста, не будьте резкими в своих ответах, если вы обнаружили что-то неприятное в моем коде, пожалуйста, отметьте это для меня 🙂

1 ответ
1

Честно говоря, не пытайтесь изобретать новые способы делать что-то, а вместо этого изучите хорошо задокументированные способы делать что-то, например MediatR и CQRS.

При именовании вещей следуйте рекомендациям Microsoft: в именах свойств, классов и т. Д. Разрешены только буквенно-цифровые символы (исключение составляет подчеркивание в начале частной переменной-члена).

Используйте читаемые имена. Ar_Name и En_Name бессмысленны. Create_User и подобные — это названия методов, а не свойств.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *