Веб-сервис, который получает данные из нескольких таблиц в базе данных, используя основной базы данных-Первый подход эф


Я никогда не создал веб-службу. Я за большинство это Pluralsight учебник, чтобы дать мне представление о том, как создать с помощью ASP.NET в MVC вместе с .Объем ядра 2.0 и сущность структуры ядра.

Цель этого веб-сервиса является предоставление пользователям данных из базы данных. Это действительно не делать ничего другого, кроме фильтрации данных, что было предложено, а затем вернуть эти данные.

Вот пример текста запроса:

{
    "buildIds": [
        "BuildId.1",
        "BuildId.2"
    ],
    "cRs": [
        100,
        400
    ]
}

В buildIds собственность-это то, что используется для получения "АСБ". В cRs свойство используется для фильтрации этих СМО вниз к определенному набору. В cRs собственность может быть опущена, если пользователь не хочет фильтровать все что угодно.

Этот вопрос несколько двоякий: я хотел бы знать, если есть какие-то другие дела, по которым я должен обрабатывать определенные вещи в качестве запросов, а также что вы думаете о моем коде в целом.

Контроллер:

[Route("api/metabuildCRs")]
public class MetabuildCRsController : Controller
{
    private IQSARepository _repository;

    public MetabuildCRsController(IQSARepository repository)
    {
        _repository = repository;
    }

    [HttpPost] // POST is used here because you can't send a body with GET
    public IActionResult GetMetabuildCrs([FromBody] MetabuildCRsRequest model)
    {
        if (model == null || model.BuildIds == null) {
            return BadRequest();
        }

        var metabuildCRs = new List<MetabuildCR>();
        foreach (var productBuildId in model.BuildIds) {
            var imageBuildIds = _repository.GetImageBuildsInProductBuild(productBuildId);
            foreach (var imageBuildId in imageBuildIds) {
                var crNumbers = _repository.GetJobDetailsForSoftwareImageBuild(imageBuildId)?
                    .Select(jd => jd.ChangeRequestNumber)
                    .Distinct();

                if (model.CRs != null && model.CRs.Count() > 0) {
                    // filter down to only crs we care about
                    crNumbers = crNumbers.Where(cr => model.CRs.Contains(cr));
                }

                foreach (var crNumber in crNumbers) {
                    var imageBuild = _repository.GetSoftwareImageBuild(imageBuildId);
                    var bulletinInfo = _repository.GetBulletinInformationForCR(crNumber);
                    var exception = _repository.GetCRException(crNumber, imageBuildId);
                    var dependentCRs = _repository.GetCRsThatDependOnCR(crNumber);

                    metabuildCRs.Add(new MetabuildCR {
                        ChangeRequestNumber = crNumber,
                        // Build Info
                        SoftwareImageBuildId = imageBuildId,
                        BuildDate = imageBuild.CrmbuildDate,
                        // Exception Info
                        RequestText = exception?.RequestText,
                        RequestedBy = exception?.RequestedBy,
                        RequestedOn = exception?.RequestedOn,
                        ExpiresOn = exception?.ExpiresOn,
                        JiraIssueKey = exception?.JiraIssueKey,
                        ReasonCode = exception?.ReasonCode,
                        ResponseBy = exception?.ResponseBy,
                        ResponseText = exception?.ResponseText,
                        ResponseOn = exception?.ResponseOn,
                        ExemptionNotes = exception?.Notes,
                        //Bulletin Info
                        SecurityBulletinDcn = bulletinInfo?.SecurityBulletinDcn,
                        DocumentType = bulletinInfo?.DocumentType,
                        DocumentReleaseDate = bulletinInfo?.DocumentReleaseDate,

                        DependentCRs = dependentCRs
                    });
                }
            }
        }

        return Ok(metabuildCRs);
    }
}

Объект запроса:

public class MetabuildCRsRequest
{
    public IEnumerable<string> BuildIds { get; set; }
    public IEnumerable<int> CRs { get; set; }
}

Хранилище (уровень сервиса):

public class QSARepository : IQSARepository
{
    private QSAContext _context;

    public QSARepository(QSAContext context)
    {
        _context = context;
    }

    public IEnumerable<string> GetImageBuildsInProductBuild(string buildId)
    {
        return _context.SoftwareProductBuildCompositions.Where(x => x.SoftwareProductBuildId == buildId)?.Select(y => y.SoftwareImageBuildId);
    }

    public SoftwareImageBuild GetSoftwareImageBuild(string buildId)
    {
        return _context.SoftwareImageBuilds.FirstOrDefault(sib => sib.SoftwareImageBuildId == buildId);
    }

    public IEnumerable<VerifySourceJobDetail> GetJobDetailsForSoftwareImageBuild(string buildId)
    {
        var crNumbers = (from job in _context.VerifySourceJobs
                join details in _context.VerifySourceJobDetails on job.Id equals details.VerifySourceJobId
                where job.SoftwareImageBuildId == buildId
                select details).Distinct();

        return crNumbers;
    }

    public CRException GetCRException(int crNumber, string softwareImage)
    {
        return _context.CRExceptions.FirstOrDefault(e => e.ChangeRequestNumber == crNumber && e.SoftwareImage == softwareImage);
    }

    public PrismCRDocument GetBulletinInformationForCR(int crNumber)
    {
        return _context.PrismCRDocuments.FirstOrDefault(b => b.ChangeRequestNumber == crNumber);
    }

    public IEnumerable<int> GetCRsThatDependOnCR(int crNumber)
    {
        return from r in _context.PrismCRRelationships
               where r.ChangeRequestNumber2 == crNumber && r.Relationship == "DependsOn"
               select r.ChangeRequestNumber1;
    }
}


Комментарии
1 ответ

Контроллеры должны быть как можно более худой. Попробуйте добавить еще один слой абстракции конкретного контроллера для того, чтобы отделить проблемы.

public interface IMetabuildCRsService  {
List<MetabuildCR> GetMetabuildCrs(IEnumerable<string> BuildIds, IEnumerable<int> CRs = null);
}

Его реализация позволит инкапсулировать функциональность в настоящее время в контроллере.

public class DefaultMetabuildCRsService : IMetabuildCRsService {
private readonly IQSARepository repository;

public DefaultMetabuildCRsService(IQSARepository repository) {
this.repository = repository;
}

public List<MetabuildCR> GetMetabuildCrs(IEnumerable<string> BuildIds, IEnumerable<int> CRs = null){
var metabuildCRs = new List<MetabuildCR>();
foreach (var productBuildId in BuildIds) {
var imageBuildIds = repository.GetImageBuildsInProductBuild(productBuildId);
foreach (var imageBuildId in imageBuildIds) {
var crNumbers = repository.GetJobDetailsForSoftwareImageBuild(imageBuildId)?
.Select(jd => jd.ChangeRequestNumber)
.Distinct();

if (CRs != null && CRs.Count() > 0) {
// filter down to only crs we care about
crNumbers = crNumbers.Where(cr => CRs.Contains(cr));
}

var imageBuild = repository.GetSoftwareImageBuild(imageBuildId);
foreach (var crNumber in crNumbers) {
var bulletinInfo = repository.GetBulletinInformationForCR(crNumber);
var exception = repository.GetCRException(crNumber, imageBuildId);
var dependentCRs = repository.GetCRsThatDependOnCR(crNumber);

metabuildCRs.Add(new MetabuildCR {
ChangeRequestNumber = crNumber,
// Build Info
SoftwareImageBuildId = imageBuildId,
BuildDate = imageBuild.CrmbuildDate,
// Exception Info
RequestText = exception?.RequestText,
RequestedBy = exception?.RequestedBy,
RequestedOn = exception?.RequestedOn,
ExpiresOn = exception?.ExpiresOn,
JiraIssueKey = exception?.JiraIssueKey,
ReasonCode = exception?.ReasonCode,
ResponseBy = exception?.ResponseBy,
ResponseText = exception?.ResponseText,
ResponseOn = exception?.ResponseOn,
ExemptionNotes = exception?.Notes,
//Bulletin Info
SecurityBulletinDcn = bulletinInfo?.SecurityBulletinDcn,
DocumentType = bulletinInfo?.DocumentType,
DocumentReleaseDate = bulletinInfo?.DocumentReleaseDate,

DependentCRs = dependentCRs
});
}
}
}
return metabuildCRs;
}
}

Это упрощает контроллер

[Route("api/metabuildCRs")]
public class MetabuildCRsController : Controller {
private readonly IMetabuildCRsService service;

public MetabuildCRsController(IMetabuildCRsService service) {
this.service = service;
}

[HttpPost]
public IActionResult GetMetabuildCrs([FromBody] MetabuildCRsRequest model) {
if (model == null || model.BuildIds == null) {
return BadRequest();
}

List<MetabuildCR> metabuildCRs = service.GetMetabuildCrs(model.BuildIds, model.CRs);

return Ok(metabuildCRs);
}
}

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

Сервис может быть изменен независимо от контроллера. Она также может быть повторно, если это необходимо.

Я лично не большой поклонник использования префиксов подчеркивания в именах переменных, так увидите, что я удалил их все.

Что касается вашего беспокойства о дополнительного функционала, они могут быть изолированы на собственные абстракции обслуживание и добавила к этому контроллеру или собственным контроллером в зависимости от вашего выбора. Дробление функциональности на мелкие простота в обслуживании модулей помогает отделить проблемы в приложении и позволяет коду тихонько расти

1
ответ дан 3 апреля 2018 в 10:04 Источник Поделиться