AutoQuery не получает имя соединения с БД при запуске через шлюз - PullRequest
1 голос
/ 30 сентября 2019

У меня есть реализация, где я вызываю операцию автозапроса через сервисный шлюз. Сервисный шлюз будет успешно вызывать как внутренние, так и внешние операции. Однако любая операция автозапроса завершается сбоем, поскольку она не получает строку подключения. Эти же операции автозапроса прекрасно работают при непосредственном вызове, а не через шлюз.

Вот трассировка стека.

at ServiceStack.OrmLite.OrmLiteConnectionFactory.CreateDbConnection() in C:\\BuildAgent\\work\\27e4cc16641be8c0\\src\\ServiceStack.OrmLite\\OrmLiteConnectionFactory.cs:line 70\r\n   at ServiceStack.OrmLite.OrmLiteConnectionFactory.OpenDbConnection() in C:\\BuildAgent\\work\\27e4cc16641be8c0\\src\\ServiceStack.OrmLite\\OrmLiteConnectionFactory.cs:line 95\r\n   at ServiceStack.ServiceStackHost.GetDbConnection(IRequest req) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\ServiceStackHost.Runtime.cs:line 691\r\n   at ServiceStack.AutoQuery.GetDb(Type type, IRequest req) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack.Server\\AutoQueryFeature.cs:line 598\r\n   at ServiceStack.AutoQuery.CreateQuery[From](IQueryDb`1 dto, Dictionary`2 dynamicParams, IRequest req) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack.Server\\AutoQueryFeature.cs:line 608\r\n   at IDOE.SecurityPortal.Api.ServiceInterface.OrganizationUserStaffTypeService.Get(QueryOrganizationUserStaffTypes query) in E:\\source\\repos\\Azure - Security Portal\\src\\IDOE.SecurityPortal\\IDOE.SecurityPortal.Api.ServiceInterface\\OrganizationUserStaffTypeService.cs:line 47\r\n   at ServiceStack.Host.ServiceRunner`1.<ExecuteAsync>d__15.MoveNext() in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\Host\\ServiceRunner.cs:line 133

Регистрация подключения к базе данных в startup.cs

    var dbFacotry = container.Resolve<IDbConnectionFactory>();
    dbFacotry.RegisterConnection("SecPortal", AppSettings.Get<string>("SQLSERVER-SECPORTAL-CONNECTIONSTRING"), SqlServer2017Dialect.Provider);
    dbFacotry.RegisterConnection("EdfiMdm", AppSettings.Get<string>("SQLSERVER-EDFIMDM-CONNECTIONSTRING"), SqlServer2017Dialect.Provider);

    Plugins.Add(new AutoQueryFeature { IncludeTotal = true });

Определение AutoQuery

[Authenticate]
[RequiredClaim("scope", "secprtl-read")]
[Route("/files", Verbs = "GET")]
[ConnectionInfo(NamedConnection = "SecPortal")]
public class QueryFiles : QueryDb<Types.File>
{
    [QueryDbField(Field = "Id", Template = "({Value} IS NULL OR {Field} = {Value})")]
    public int? Id { get; set; }

    [QueryDbField(Field = "FileName", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
    public string FileName { get; set; }

    [QueryDbField(Field = "UserId", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
    public string UserId { get; set; }

    [QueryDbField(Field = "StateOrganizationId", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
    public string StateOrganizationId { get; set; }

    [QueryDbField(Field = "Notes", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
    public string Notes { get; set; }
}

Код вызова службы

public class ContactService : Service
{

    public ContactService()
    {
    }

    public async Task<object> Post(PostContact request)
    {
        try
        {
            var files = base.Gateway.Send(new QueryFiles() { });

            return new Contact() { Name = request.Name };
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }


}

Шлюз настраиваемой службы

public class CustomServiceGatewayFactory : ServiceGatewayFactoryBase
{

    private IRequest request;

    public override IServiceGateway GetServiceGateway(IRequest request)
    {
        this.request = request;
        return base.GetServiceGateway(request);
    }

    public override IServiceGateway GetGateway(Type requestType)
    {
        var isLocal = HostContext.Metadata.RequestTypes.Contains(requestType);

        if (isLocal)
        {
            return base.localGateway;
        }
        else
        {
            return new JsonServiceClient("https://localhost:6001")
            {
                BearerToken = request.GetBearerToken()
            };
        }
    }

}

Регистрация шлюза настраиваемой службы в startup.cs

container.Register<IServiceGatewayFactory>(x => new CustomServiceGatewayFactory()).ReusedWithin(ReuseScope.None);

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


Я создал собственный метод автозапроса в интерфейсе сервиса и заметил, что информация о соединении с БД не была заполнена в массиве request.items. Поэтому я вручную добавил эту информацию в запрос, и она работала, как и ожидалось. Так или иначе, в моей настройке, операции автозапроса, которые вызываются локально, информация о соединении с БД не добавляется к объекту запроса.

1 Ответ

0 голосов
/ 01 октября 2019

Атрибуты фильтра запросов подобно [ConnectionInfo] применяется только к запросам HTTP, а не к внутренним запросам шлюза служб.

Информация о соединении не настроена, так как она не аннотирована в вашем PostContact DTO о сервисном запросе, который вызывает входящий сервисный шлюз.

Вы можете иметь [ConnectionInfo] на QueryFiles AutoQuery Запрос DTO, прикрепленный к текущему Запросу:

public async Task<object> Post(PostContact request)
{
    try
    {
        typeof(QueryFiles).FirstAttribute<ConnectionInfoAttribute>()
            .Execute(Request,Response,request);

        var files = base.Gateway.Send(new QueryFiles() { });

        return new Contact() { Name = request.Name };
    }
    catch (Exception ex)
    {
        throw ex;
    }
}
...