在(ServiceStack)ServiceA中“共享”/解析(ServiceStack)ServiceB是一个坏主意吗

本文关键字:ServiceStack 一个 ServiceA 共享 解析 ServiceB | 更新日期: 2023-09-27 18:34:41

在我们的代码库中,我看到了不同ServiceStack服务之间的一些共享(我认为不合适(。我认为这不是一个好主意,因为每个服务的"边界"变得复杂。例如,通过"边界",它可以表示数据库连接的边界,我将使用数据库连接边界作为示例来说明我的意思。

例如,如果我有以下两个服务。

[Route("/service-a/", Verbs = "POST")]
public class DtoServiceA : IReturn<IList<string>>
{
}
public class ServiceA : Service //service stack service
{
    public ServiceA(Funq.Container container) : base(container)
    {
        _container = container; //I didn't type the full code
    }
    public IList<string> Post(DtoServiceA request)
    {
        //do something that belongs to ServiceA
        //then resolve ServiceB and call Post() from ServiceB
        Container.Resolve<ServiceB>().Post(new DtoServiceB());
        return new List<string>();
    }
}
[Route("/service-b/", Verbs = "POST")]
public class DtoServiceB : IReturn<IList<string>>
{
}
public class ServiceB : Service //service stack service
{
    public ServiceB(Funq.Container container) : base(container)
    {
        _container = container; //I didn't type the full code
    }
    public IList<string> Post(DtoServiceB request)
    {
        //do something that belongs to ServiceB
        return new List<string>();
    }
}

假设如果我像这样在 Post 方法中控制数据库连接

    public IList<string> Post(DtoServiceA request)
    {
        //suppose if I control db connection like so
        using (var conn = IDbConnectionFactory.Open())
        {
            //do something that belongs to ServiceA
            //then resolve ServiceB and call Post() from ServiceB
            Container.Resolve<ServiceB>().Post(new DtoServiceB());
            //above line will fail because connection has already been opend by ServiecA.Post()
        }
    }
    public IList<string> Post(DtoServiceB request)
    {
        //suppose if I control db connection like so
        using (var conn = IDbConnectionFactory.Open())
        {
        }
    }

因为数据库连接已经打开,所以显然这不是"共享"服务的好方法。但是我们有一种更复杂的方法来打开数据库连接,基本上它会计数/检测它是否打开,因此不会多次打开连接。但这对我来说是代码气味。

我在其他地方已经有人建议以类似的方式共享服务。我不是100%相信这是个好建议。

我可能会做下面这样的事情,并将 using 语句中的代码提取到一个单独的类/类中。

    public IList<string> Post(DtoServiceA request)
    {
        //suppose if I control db connection like so
        using (var conn = IDbConnectionFactory.Open())
        {
            //move code to a searapte "none servicestack service", which
            //can be just a normal c# class
            //so that the "boundary" is being controlled at service stack level
            //and the actual code that does the job is extracted elsewhere
            Resolve<NoneServiceStackServiceA>().DoSomething();
            Resolve<NoneServiceStackServiceB>().DoSomething();
        }
    }
    public IList<string> Post(DtoServiceB request)
    {
        //suppose if I control db connection like so
        using (var conn = IDbConnectionFactory.Open())
        {
            //move code to a searapte "none servicestack service", which
            //can be just a normal c# class
            //so that the "boundary" is being controlled at service stack level
            //and the actual code that does the job is extracted elsewhere
            Resolve<NoneServiceStackServiceB>().DoSomething();
        }
    }

欢迎任何建议/建议。谢谢。

在(ServiceStack)ServiceA中“共享”/解析(ServiceStack)ServiceB是一个坏主意吗

从资源使用的角度来看,这不是一个坏主意,因为打开额外的数据库连接对于连接池(SqlServer 的默认值(非常轻量级。

如果调用服务类似于"聚合服务",它只是将多个服务的输出组合到单个服务响应中,则很好,罗斯文客户详细信息服务中的示例如下:

public class CustomerDetailsService : Service
{
    public CustomerDetailsResponse Get(CustomerDetails request)
    {
        var customer = Db.SingleById<Customer>(request.Id);
        using (var orders = base.ResolveService<OrdersService>())
        {
            var ordersResponse = orders.Get(new Orders { CustomerId = customer.Id });
            return new CustomerDetailsResponse
            {
                Customer = customer,
                CustomerOrders = ordersResponse.Results,
            };
        }
    }
}

否则,从代码架构的角度来看,它并不理想,因为它模糊了依赖关系图,我更愿意在共享依赖或扩展方法中提取通用功能,例如:

ServiceA
  - SharedDep
ServiceB
  - SharedDep

避免服务响应中的接口

附带说明一下,我强烈建议不要在服务响应中使用接口。集合很少被嘲笑,IList<T>特别无用,因为它实际上总是隐藏一个具体的List<T>,它需要转换为该才能访问其有用的LINQ扩展方法。