Dear RemObjects Support,
I am trying to integrate RemObjects DataAbstract into a standard .NET Core RazorPages template project. The integration works well with Microsoft Dependency Injection, and the server starts successfully. Below is the code I use for the integration:
using RemObjects.DataAbstract.Server;
using RemObjects.SDK.Extensions;
using WebRodaApp;
using WebRodaApp.Services;
[assembly: HostingStartup(typeof(ConfigureRODA))]
namespace WebRodaApp;
public class ConfigureRODA : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder
.ConfigureServices((context, services) =>
{
services
.AddHostedService<RodaWorker>()
.AddInfrastructureServices<AppServerEngine>(HostExtensions.GetAppServerConfiguration(configuration =>
{
configuration.ApplicationName = "WebRodaApp";
configuration.RodlNamespace = "WebRodaApp";
}))
.AddApplicationServices()
.AddNetworkServerConfiguration(server =>
{
server.Port = 8099;
})
.AddDataAbstract(context.Configuration);
});
}
}
public static class DataAbstractExtensions
{
public static IServiceCollection AddDataAbstract(this IServiceCollection services, IConfiguration configuration)
{
if (Configuration.Loaded) return services;
Configuration.Load();
var connectionManager = new ConnectionManager();
var connectionString = configuration.GetValue<string>("DataAbstract:ConnectionsDb");
connectionManager.AddDefinition("Connections", connectionString);
var service = Engine.AcquireLocalService(nameof(ConnectionsService), Guid.Empty) as ConnectionsService;
service?.SetConnections();
return services;
}
}
internal sealed class RodaWorker(IAppServerEngine engine) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
engine.Initialize();
engine.Start();
try
{
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(1000, stoppingToken);
}
}
finally
{
engine.Stop();
}
}
}
The challenge arises when I attempt to call a method defined in a DataAbstract service (ConnectionsService) directly from the server application. According to the documentation, I need to use AcquireLocalService, which works as long as the service constructor is parameterless. However, when I modify the service constructor to include dependencies (e.g., ILogger), I encounter an error indicating that a parameterless constructor is required.
Below is the code for my ConnectionsService implementation:
using RemObjects.DataAbstract.Linq;
using RemObjects.DataAbstract.Server;
using RemObjects.SDK.Server;
using WebRodaApp.Models;
using Engine = RemObjects.DataAbstract.Server.Engine;
namespace WebRodaApp.Services
{
[Service]
public class ConnectionsService: DataAbstractService
{
private readonly ILogger? _logger;
public ConnectionsService(ILogger logger): this()
{
_logger = logger;
}
public ConnectionsService()
{
AcquireConnection = true;
ServiceDataStreamer = new RemObjects.DataAbstract.Bin2DataStreamer();
ServiceSchemaName = "Connections";
}
public List<(string name, string path)> GetConnections()
{
_logger?.Log("GetConnections called");
var lda = new LinqLocalDataAdapter(this, Guid.Empty);
var result = from c in lda.GetTable<databases>()
select new { c.name, c.path };
return result.Map(x => (x.name, x.path));
}
[ServiceMethod]
public void SetConnections()
{
_logger?.Log("SetConnections called");
var connectionString = Engine.ConnectionManager.ConnectionDefinitions.FindItem("Connections").ConnectionString;
foreach (var conn in GetConnections())
{
var found = Engine.ConnectionManager.ConnectionDefinitions.FindItem(conn.name);
if (found != null) continue;
Engine.ConnectionManager.AddDefinition(conn.name, connectionString.ReplaceDatabase(conn.path));
}
}
}
}
My goal is to use Dependency Injection for service dependencies, such as ILogger, while still being able to call the service from within the server application.
Additionally, can you confirm if I am correctly integrating DataAbstract (and SDK) with the ConfigureRODA class?
Thank you in advance for your assistance!
Best regards,
Dejan