public partial class Startup
{
partial void OnConfigureServices(IServiceCollection services)
{
services.AddDbContext<GslpaMdev.Data.GslpamDbContextRLS>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("GslpamDbConnection"));
});
}
}
}
This should call the following custom class "GslpamDbContext.Custom.cs":
namespace GslpaMdev.Data
{
public partial class GslpamDbContextRLS : Microsoft.EntityFrameworkCore.DbContext
{
private readonly string UserId;
private readonly IHttpContextAccessor httpAccessor;
//Setting sql session state in constructor
public GslpamDbContextRLS(IHttpContextAccessor httpAccessor, DbContextOptions<GslpamDbContextRLS> options):base(options)
{
this.Database.OpenConnection();
this.httpAccessor = httpAccessor;
UserId = httpAccessor.HttpContext.User.FindFirst(ClaimTypes.Name).Value;
SetUserIdInSqlSession();
}
private void SetUserIdInSqlSession()
{
var sqlParameter = new SqlParameter("@UserId", UserId);
this.Database.ExecuteSqlRaw(
sql: "EXEC SP_SET_SESSION_CONTEXT @key=N'UserId' ,@value=@UserId",
parameters: sqlParameter);
}
public GslpamDbContextRLS(IHttpContextAccessor httpAccessor)
{
this.httpAccessor = httpAccessor;
}
}
}
But it doesn`t work at all.
Note: it works if I paste the code to my default generated "GslpamDbContext.cs" and let it call from default Startup.cs, but I don`t want to add these files to code generation ignore list...
I want to inject current UserId in DB SessionContext, so I need access to the httpAccessor to get current UserId from context. The default generated GslpamDbContext.cs has all the properties to achieve this. So I set up a custom DbContext class for this purpose only.
This is again not a proper way to use a partial class not to mention that the constructor of the DbContext and the DbContext in general is too early to get the authenticated user. The extension point in the DbContext that is added by Radzen is OnModelBuilding partial method
If it’s available for you in constructor then it will be in the partial method I’ve showed you how to use. I’m afraid that I cannot add anything else to this thread.
It's not clear exactly what you are trying to achieve.
Does the user log in and if so how?
Don't you need to run your code after the user successfully logs in?
User logs on at my radzen app (radzen internal security). At this moment, DB Connection has to be injected with "SP_SET_SESSION_CONTEXT" which writes current UserId to DB_SessionContext to enable RowLevelSecurityPolicy.
I want to achieve exactly what is described in this article, but I need to do it with custom classes as it wouldn´t be good to add default DbContext.cs to the code generation ignore list of radzen.
in the posted article partly EF6 has been used ("state change event"), but the approaches with "constructor" and "interceptors" work with earlier versions.
Again to clarify: i have already written several times that the constructor variant works. So I don't understand why i can't call a custom constructor in a custom class that inherits from default dbcontext.
There must be an error on my part that prevents the call from startup.cs.
@mumfie: Yes, this is exactly what I´m trying to do but at "base(options)", it shows me the following error:
Argument 1: cannot convert from 'Microsoft.EntityFrameworkCore.DbContextOptions<GslpaMdev.Data.GslpamDbContext>' to 'Microsoft.AspNetCore.Http.IHttpContextAccessor' [project]csharp(CS1503)