Dotnet Core - Entity Framework - What do the empty curly brackets mean in this context and what's the result - entity-framework

I recently read THIS post on "Implementing database per tenant strategy" by G Pelpman.
It deals with connecting to multiple databases and uses a tenant to create a connection string.
The part I am confused about and what it allows is the following registering of services.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MultitenantDbContext>(o => { });
services.AddMvc();
services.AddTransient<ITenantProvider, DummyTenantProvider>();
}
In particular,
services.AddDbContext<MultitenantDbContext>(o => { });
Whats the reason for using (o => { });?
How does it help in connecting to multiple databases?

services.AddDbContext receives an Action (Action) as a parameter...
in this case, as said in the very post you shared "Implementing database per tenant strategy", no conections will be provided by ConfigureServices(), so an empty Action is passed to services.AddDbContext() to fullfil the optionsAction param...
Connections will be further provided based on the Tenant defined on DbContextOptionsBuilder._tenant

Related

.NET 6 console app how to access configuration and get connection string for DbContext

I am writing a .NET 6 console app and have this unfinished code below. I don't know how to get the connection string from configuration such that I can pass it to the options.UseSqlServer method.
I prefer using the top level statements template.
Also, should I call hostBuilder.Build().Run(); at the end of this code? Or just hostBuilder.Build()? Just wondering what the difference is.
var hostBuilder = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, builder) =>
{
builder.SetBasePath(Directory.GetCurrentDirectory());
})
.ConfigureServices((context, services) =>
{
services.AddDbContext<CompanyContext>(options => options.UseSqlServer("<connection string from config"));
});
An ASP.NET Core web app is actually a console app that starts an HTTP server. The DI, logging, configuration infrastructure is the same in both cases. The same methods you see in ASP.NET Core tutorials can be used in console applications through the Generic Host Builder.
The Configuration is available through the HostBuilderContext parameter of the ConfigureServices delegate :
.ConfigureServices((context, services) =>
{
var cns=context.Configuration.GetConnectionString("MyConnection");
services.AddDbContext<CompanyContext>(options.UseSqlServer(cns));
});
The WebApplicationBuilder class introduced in .NET (Core) 6.0 still uses the Microsoft.Extensions.Hosting middleware under the hood, but exposes Services, Configuration, Logging etc as properties instead of methods like ConfigureServices to enable top-level and minimal API programs.
I am working on a .NET 6.0 console app with EFCore and I have exactly the same issue. Thanks to your answers I could manage to make the db-scaffolding to work again...
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((config) =>
{
config.AddJsonFile("appsettings.json");
config.AddEnvironmentVariables();
config.Build();
})
.ConfigureServices((context, services) =>
{
var cns = context.Configuration.GetConnectionString("DiBerieBotDB");
services.AddDbContext<DiBerieBotEntities>(options => options.UseSqlServer(cns))
//.AddHostedService<DiBerieBotMain>();
;
})
.Build();
List<User> theUsers = new List<User>();
using (var context = new DiBerieBotEntities())
{
theUsers = (from usr in context.Users.Include("Channels")
select usr).ToList();
}
host.Run();
but on the first Linq query that occurs, the program crashs :
Crash on running Linq query
Also my console app "DiBerieBot.Console" and the DAL "DiBerieBot.DAL" (where the EFCore DbContext class is) are on separate projects :
Projects
Any idea ?

IdentityServer4 ConfigurationDbContext not loading client secrets

I want to display a list of clients and their secrets in an admin-only page of an MVC app baked into my IdentityServer project that is using EntityFramework.
I currently have a reference to ConfigurationDbContext in my controller from dependency injection and can access the client details. However, the ClientSecrets property of each client returned from the context does not have the secrets loaded, and is set to null. How can I force the context to load the ClientSecrets, which are stored in another table? Is there a different way I should be doing this?
Because the entity framework saved the client secrets in the separate table you have to use the entity framework's extension method - Include.
public class ApplicatonsService : IApplicationsService
{
private readonly ConfigurationDbContext is4Context;
public ApplicatonsService(ConfigurationDbContext is4Context)
{
this.is4Context = is4Context;
}
public Task<List<Client>> GetApplicationsAsync()
{
return Task.FromResult(is4Context.Clients
.Include(c => c.ClientSecrets)
.Select(c => c.ToModel()).ToList());
}
...
}

Explicit transaction for entire request duration with automatic commit/rollback on errors (EF6, Web API2, NInject)

I'm starting a new Web API application, and I'm unsure how to handle transactions (and subsequent rollbacks in case of exceptions).
My overall goal is so have a single database connection per request, and have the entire thing wrapped in an explicit transaction.
I'll need an explicit transaction since I will be executing stored procedures aswell, and need to rollback any results from those if my application should throw any exceptions.
My plan was to re-use an approach I've used in MVC applications in the past which in rough terms was simply binding my database context to requestscope using ninject and then handling rollback/commit in the ondeactivation event.
Let's say I have a controller with two methods.
public class MyController : ApiController {
public MyController(IRepo repo) {
}
}
public string SimpleAddElement() {
_repo.Add(new MyModel());
}
public string ThisCouldBlowUp() {
// read from context
var foo = _repo.ReadFromDB();
// execute stored prodecure which changes some content
var res = _repo.StoredProcOperation();
// throw an exception due to bug/failsafe condition
if (res == 42)
throw Exception("Argh, an error occured");
}
}
My repo skeleton
public class Repo : IRepo {
public Repo(IMyDbContext context) {
}
}
From here, my plan was to simply bind the repositories using
kernel.Bind<IRepo>().To<Repo>();
and provide a single database context per request using
kernel.bind<IMyDbContext>().To<CreateCtx>()
.InRequestScope()
.OnDeactivate(FinalizeTransaction);
private IMyDbContext CreateCtx(IMyDbContext ctx) {
var ctx = new DbContext();
ctx.Database.BeginTransaction();
}
private void FinalizeTransaction(IMyDbContext ctx) {
if (true /* no errors logged on current HttpRequest.AllErrors */)
ctx.Commit();
else
ctx.Rollback();
}
Now, if I invoke SimpleAddElement from my browser FinalizeTransaction never gets invoked... So either I'm doing something wrong suddently, or missing something related to WebAPI pipeline
So how should I go about implementing a transactional "single DB session per request"-module?
What is best practise ?
If possible, I'd like the solution to support ASP vNext aswell
I suppose one potential solution could dropping the "ondeactivation" handler and implementing an HTTP module which will commit in Endrequest and rollback in Error... but there's just something about that I dont like.
You are missing an abstraction in your code. You execute business logic inside your controller, which is the wrong place. If you extract this logic to the business layer and hide it behind an abstraction, it will be trivial to wrap all business layer operations inside a transaction. Take a look at this article for some examples of this.

Securing Entities with Claims Based Authorization in Web Api 2 OData Endpoint

Given the following Controller
namespace MyNamespace.Api.Controllers
{
[Authorize]
public class AccountController : ODataController
{
private Entities db = new Entities();
// GET odata/Account
[Queryable]
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Read", Resource = "Account")]
public IQueryable<Account> GetAccount()
{
return db.Accounts();
}
...
}
}
I override the ClaimsAuthorizationManager.CheckAccess(...)
public class AuthorizationManager : ClaimsAuthorizationManager
{
public override bool CheckAccess(AuthorizationContext context)
{
var resource = context.Resource.First().Value;
var action = context.Action.First().Value;
return Policies.Validate(resource, action);
}
}
This is useful only to the point where I can check whether or not the Current Principal in general can Read Account. However, if I'd want to check which accounts a certain user is allowed to Read, I am lost.
Let's say I have a Manager user who should be able to read all Accounts for which he is a manager for whereas a non-manager user should be able to read only their own account.
Is there a best practice for this or have you done something like this previously and give me a few hints to look for?
I do not use ClaimsPrincipalPermissionAttribute because I cannot pass any dynamic parameters to it like requested Account from your sample.
Have a look at the book "Pro APS.NET Web API Security" page 97. They suggest to invoke AuthorizationManager from your controller action implementation by code new IdentityConfiguration().ClaimsAuthorizationManager.CheckAccess(context), where context is constructed manually so you can pass Account requested (for example) as Resource to check it in your AuthorizationManager implementation.
Also have a look at pluralsight training "Introduction to Identity and Access Control in .NET 4.5". There are also some info about how to implement claim-based security in Web API.
Now I am in progress of implementing the security you are talking about and I am interesting in the subject too.
My case is: role Administrator is assigned by Country, every Administrator can see entities only related to the countries they have access to.
UPDATE: After several projects I forgot about Claims-based security as this is extremely difficult way to make security checks. Today I use decorator pattern where all the security checks are done. It appears to be very easy to implement security even in OData Controllers like this:
public IQueriable MyQuriableEntitySet
{
get{ return implementationWithoutSecurity.MyQuriableEntitySet.Where(e=>e.Country.Code = currentUser.AssignedTo.CountryCode || currentUser.IsSuperAdmin); }
}

No data available with Entity Framework when consumed by second project

I have a web app that uses EF5 to map to a SQL database. This is the standard membership database with some additional tables I've added. Works like a champ in that project.
I have a second project, a windows service running TCP a server, which needs to insert items into the same database. So I reference the web app from this second project and can see my DbContext and entity types as needed.
At runtime, however, none of my DbSets gets populated with data. I have tried explicitly opening the connection to execute queries too, like this:
public MyContext()
: base("DefaultConnection")
{
try
{
Database.Connection.Open();
var command = new System.Data.SqlClient.SqlCommand("SELECT * FROM dbo.Trackers", (SqlConnection) Database.Connection);
var reader = command.ExecuteReader();
bool result = reader.Read();
}
catch (Exception exception)
{
//handle exception
}
this.Database.Connection.Close();
}
The result is false, but the connection is created and the reader is aware that I have four fields in my table. Is anyone aware of a reason this should work in my web app but not in a referencing app?
I had forgotten that the connection string from the web.config file is only honored when running as a web app. The TCP service .exe needs its own copy of the connection string in App.config. It just happened that the default (implicit) connection string on my TCP service connected to a valid, but empty, copy of my database.