Your EF dependencies should work like any other registered IOC dependency, you’ll need to refer to Microsoft docs for how to configure your EF DataContext properly - we can provide support for any ServiceStack libraries, not 3rd party ones.
But I’ve quickly test that this works as expected by creating a new empty Web Template:
$ x new web EFTest
Then add the EF dependency in both your EFTest.csproj
& EFTest.ServiceInterface.csproj
:
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.6" />
<PackageReference Include="ServiceStack" Version="5.*" />
</ItemGroup>
I then registered a basic BloggingContext
as they refer to in their docs in ConfigureServices()
which registers the IOC dependency. To create the tables I used the RelationalDatabaseCreator as mentioned in this StackOverflow answer which should only be run once to create the table and insert a row.
public class Startup : ModularStartup
{
public new void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(opt => opt.UseSqlServer(str));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
SeedBlogs(app); // run once to create Blogs table and insert row
//..
}
private static void SeedBlogs(IApplicationBuilder app)
{
using var scope = app.ApplicationServices.CreateScope();
using var context = scope.ServiceProvider.GetService<BloggingContext>();
var databaseCreator = (RelationalDatabaseCreator)
context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();
context.Blogs.Add(new Blog { Title = "Title", Content = "Content" });
context.SaveChanges();
}
}
The BloggingContext
and all DB Models should be defined in your ServiceInterface project
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
}
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
[Route("/blogs")]
public class GetBlogs : IReturn<GetBlogsResponse> {}
public class GetBlogsResponse
{
public List<Blog> Results { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
The BloggingContext
EF Dependency should be injected in your Services as normal:
public class MyServices : Service
{
private BloggingContext db;
public MyServices(BloggingContext db) => this.db = db;
public object Any(GetBlogs request)
{
return new GetBlogsResponse { Results = db.Blogs.ToList() };
}
}
And this should work as expected, with the BloggingContext
being injected with the Service being able to use it in Services as above.
Another way to access scoped dependencies is using the ResolveScoped
API, which resolves the dependency from .NET Core Request Scope:
public class MyServices : Service
{
public object Any(GetBlogs request)
{
using (var db = Request.ResolveScoped<BloggingContext>())
{
return new GetBlogsResponse { Results = db.Blogs.ToList() };
}
}
}
Not sure what issue you’re having but I was able to use EF Core by following the Microsoft docs for configuring the DB Context,
If your Response DTO has a ResponseStatus property it should get injected with the Exception Info.
A quick way to inspect the Exception thrown in a Service is to override OnExceptionAsync() in your Service:
public class MyServices : Service
{
public override Task<object> OnExceptionAsync(object request, Exception ex)
{
var s = ex.ToString();
return base.OnExceptionAsync(request, ex);
}
}
Whilst you can inspect every Service Exception by Overriding OnExceptionTypeFilter in your AppHost:
public class AppHost : AppHostBase
{
public override void OnExceptionTypeFilter(Exception ex,ResponseStatus status)
{
var s = ex.ToString();
base.OnExceptionTypeFilter(ex, status);
}
}