I Have a Multi-Tenant application and how can I use Interception in Entity Framework 7?
In Entity Framework 6, exists Interception using System.Data.Entity.Infrastructure.Interception, but don't find in version 7 of the Entity Framework.
Here's an example -> https://azure.microsoft.com/en-us/documentation/articles/web-sites-dotnet-entity-framework-row-level-security/
Interception isn't implemented yet in EFCore. It is a backlog item (see https://github.com/aspnet/EntityFramework/wiki/Roadmap)
Although EF Core does not have Interceptors, it is possible to perform QueryFilters to ensure that all queries are filtered by the tenant id.
Gunnar Peipman has a number of articles that can help you understand how to use QueryFilters for a Multi-Tenant scenario.
http://gunnarpeipman.com/2017/08/ef-core-global-query-filters/
I have somewhat some issue.
In EF Core you can use interceptors, here's some sample code that may be of use:
using System.Data.Common;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.DiagnosticAdapter;
public class CommandListener
{
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
public void OnCommandExecuting(DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, DateTimeOffset startTime)
{
//call security or other methods here.
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")]
public void OnCommandExecuted(object result, bool async)
{
//call security or other methods here.
}
}
In the constructor of your repository you do the hooking
var listener = _context.GetService<DiagnosticSource>();
(listener as DiagnosticListener).SubscribeWithAdapter(new CommandListener());
Now when you query your dbContext e.g.:
_context.employees.Where(...
Then before this query is returned the above methods OnCommandExecuting and OnCommandExecuted are executed.
So you can somewhat imitate the override of SaveChanges in EF Core.
However one important thing to note is that the return result set from the query is not accessible in the OnCommandExecuting and OnCommandExecuted methods.
Related
I would like to integrate Bot composer with Custom actions. The custom actions in turn calls different API to perform some business logic. I would like to inject interfaces and service provider to custom action. I am having trouble in doing this as it is failing and getting in to null pointer exceptions, eventhough I have added everything properly in the startup.cs. Could you please explain how can i achieve this?.
[JsonConstructor]
public MultiplyDialog(IServiceProvider serviceProvider, [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
: base()
{
serviceProvider.GetService<ApiService>() // serviceprovider always null
this.RegisterSourceLocation(sourceFilePath, sourceLineNumber);
}
You have to keep in mind that when using Adaptive Dialogs (that is, the core of Composer) Dialogs are singletons and, when using Composer, they're not instantiated from dependency injection (DI).
Also, since dialogs are singletons, you can't (well, you could but you shouldn't) use services like constructor injected DbContexts and similar (when working with the SDK, that is, coding).
The easiest way to solve this is by using HTTP requests using the HttpRequest action. This is the way that's built into the whole adaptive dialogs ecosystem to achieve this kind of functionality.
If you really insist on doing it with DI into the dialogs, you'd have to solve DI from the TurnContext and you'd have to set it up in the adapter. However, that's a bit convoluted an requires you to use a custom runtime.
UPDATE Added the way to implement DI with adaptive dialogs.
1 - Register the service class in the turn state in the adapter
public class AdapterWithErrorHandler : BotFrameworkHttpAdapter
{
public AdapterWithErrorHandler(
IConfiguration configuration,
ILogger<BotFrameworkHttpAdapter> logger,
//...
QnAClient qnaClient)
: base(configuration, logger)
{
// Add QnAClient to TurnState so we can use it while in the turn
Use(new RegisterClassMiddleware<QnAClient>(qnaClient));
//...
}
}
In the code above QnAClient is an typed HttpClient created with IHttpClientFactory so it's a safe to use singleton.
2 - Get the service from the TurnState wherever you need it
public async Task SetPropertiesAsync(DialogContext context, ...)
{
var qnaClient = context.Context.TurnState.Get<QnAClient>();
//...
}
BTW, this is a nice way to get an HttpClient properly managed by IHttpClientFactory when you register it like this in ConfigureServices:
services.AddHttpClient<QnAClient>()
.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(new[] { 1, 2, 3, 5, 8, 13 }.Select(t => TimeSpan.FromSeconds(t))))
.AddTransientHttpErrorPolicy(p => p.CircuitBreakerAsync(6, TimeSpan.FromSeconds(30)));
In this case with retry policies from Polly.
The other answer isn't super clear - so I will add some clear snippets. Say you want to inject your service MyService
First, some extra configuration:
services.AddSingleton<IMiddleware, RegisterClassMiddleware<MyService>>(sp => new RegisterClassMiddleware<MyService>(sp.GetRequiredService<MyService>()));
Then in your Dialog:
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{
var myService = dc.Services.Get<MyService>();
}
Done!
I have set up a signalR website .net core. My function in my hub is:
public async Task Notify(int id) {
await Clients.All.InvokeAsync("Notified", id);
}
I have also tested this with the following js:
let connection = new signalR.HubConnection(myURL);
connection.on('Notified', data => {
console.log(4, data);
});
connection.start();
The js code seems to work fine and I see the log when I try connection.Invoke('Notify').
Now I have a console app that can needs to make the invoke. I am trying this in two ways and don't mind either solution:
1. A mvc controller within the signalR website that can take the id and invoke 'Notified'.
2. Use the client library Microsoft.AspNetCore.SignalR.Client in the console app.
The way 1 I have only done in classic asp.net like this:
GlobalHost.ConnectionManager.GetHubContext(hubName)
But couldn't find a way to do this in .net core.
Way 2 I have used the library and tried this so far:
var con = new HubConnectionBuilder();
con.WithUrl(myURL);
var connection = con.Build();
connection.InvokeAsync("Notify",args[0]).Wait();
This is the closest I have come to create a connection in the same way as the js code. However this code throws a null pointer when calling connection.InvokeAsync. The connection object is not null. It seems to be an internal object that is null. According to the stack trace the exception is thrown when a MoveNext() function is internally called.
Well looks like both are not currently possible. As of now I just used a forced way which is hopefully temporary.
I have created and used the following base class for hubs:
public abstract class MyHub : Hub
{
private static Dictionary<string, IHubClients> _clients = new Dictionary<string, IHubClients>();
public override Task OnConnectedAsync()
{
var c = base.OnConnectedAsync();
_clients.Remove(Name);
_clients.Add(Name, Clients);
return c;
}
public static IHubClients GetClients(string Name) {
return _clients.GetValueOrDefault(Name);
}
}
GlobalHost is gone. You need to inject IHubContext<THub> like in this sample.
This can be a bug in SignalR alpha1. Can you file an issue on https://github.com/aspnet/signalr and include a simplified repro?
Is there a way to pass data to dependencies registered with either Execution Context Scope or Lifetime Scope in Simple Injector?
One of my dependencies requires a piece of data in order to be constructed in the dependency chain. During HTTP and WCF requests, this data is easy to get to. For HTTP requests, the data is always present in either the query string or as a Request.Form parameter (and thus is available from HttpContext.Current). For WCF requests, the data is always present in the OperationContext.Current.RequestContext.RequestMessage XML, and can be parsed out. I have many command handler implementations that depend on an interface implementation that needs this piece of data, and they work great during HTTP and WCF scoped lifestyles.
Now I would like to be able to execute one or more of these commands using the Task Parallel Library so that it will execute in a separate thread. It is not feasible to move the piece of data out into a configuration file, class, or any other static artifact. It must initially be passed to the application either via HTTP or WCF.
I know how to create a hybrid lifestyle using Simple Injector, and already have one set up as hybrid HTTP / WCF / Execution Context Scope (command interfaces are async, and return Task instead of void). I also know how to create a command handler decorator that will start a new Execution Context Scope when needed. The problem is, I don't know how or where (or if I can) "save" this piece of data so that is is available when the dependency chain needs it to construct one of the dependencies.
Is it possible? If so, how?
Update
Currently, I have an interface called IProvideHostWebUri with two implementations: HttpHostWebUriProvider and WcfHostWebUriProvider. The interface and registration look like this:
public interface IProvideHostWebUri
{
Uri HostWebUri { get; }
}
container.Register<IProvideHostWebUri>(() =>
{
if (HttpContext.Current != null)
return container.GetInstance<HttpHostWebUriProvider>();
if (OperationContext.Current != null)
return container.GetInstance<WcfHostWebUriProvider>();
throw new NotSupportedException(
"The IProvideHostWebUri service is currently only supported for HTTP and WCF requests.");
}, scopedLifestyle); // scopedLifestyle is the hybrid mentioned previously
So ultimately unless I gut this approach, my goal would be to create a third implementation of this interface which would then depend on some kind of context to obtain the Uri (which is just constructed from a string in the other 2 implementations).
#Steven's answer seems to be what I am looking for, but I am not sure how to make the ITenantContext implementation immutable and thread-safe. I don't think it will need to be made disposable, since it just contains a Uri value.
So what you are basically saying is that:
You have an initial request that contains some contextual information captured in the request 'header'.
During this request you want to kick off a background operation (on a different thread).
The contextual information from the initial request should stay available when running in the background thread.
The short answer is that Simple Injector does not contain anything that allows you to do so. The solution is in creating a piece of infrastructure that allows moving this contextual information along.
Say for instance you are processing command handlers (wild guess here ;-)), you can specify a decorator as follows:
public class BackgroundProcessingCommandHandlerDecorator<T> : ICommandHandler<T>
{
private readonly ITenantContext tenantContext;
private readonly Container container;
private readonly Func<ICommandHandler<T>> decorateeFactory;
public BackgroundProcessingCommandHandlerDecorator(ITenantContext tenantContext,
Container container, Func<ICommandHandler<T>> decorateeFactory) {
this.tenantContext = tenantContext;
this.container = container;
this.decorateeFactory = decorateeFactory;
}
public void Handle(T command) {
// Capture the contextual info in a local variable
// NOTE: This object must be immutable and thread-safe.
var tenant = this.tenantContext.CurrentTenant;
// Kick off a new background operation
Task.Factory.StartNew(() => {
using (container.BeginExecutionContextScope()) {
// Load a service that allows setting contextual information
var context = this.container.GetInstance<ITenantContextApplier>();
// Set the context for this thread, before resolving the handler
context.SetCurrentTenant(tenant);
// Resolve the handler
var decoratee = this.decorateeFactory.Invoke();
// And execute it.
decoratee.Handle(command);
}
});
}
}
Note that in the example I make use of an imaginary ITenantContext abstraction, assuming that you need to supply the commands with information about the current tenant, but any other sort of contextual information will obviously do as well.
The decorator is a small piece of infrastructure that allows you to process commands in the background and it is its responsibility to make sure all the required contextual information is moved to the background thread as well.
To be able to do this, the contextual information is captured and used as a closure in the background thread. I created an extra abstraction for this, namely ITenantContextApplier. Do note that the tenant context implementation can implement both the ITenantContext and the ITenantContextApplier interface. If however you define the ITenantContextApplier in your composition root, it will be impossible for the application to change the context, since it does not have a dependency on ITenantContextApplier.
Here's an example:
// Base library
public interface ITenantContext { }
// Business Layer
public class SomeCommandHandler : ICommandHandler<Some> {
public SomeCommandHandler(ITenantContext context) { ... }
}
// Composition Root
public static class CompositionRoot {
// Make the ITenantContextApplier private so nobody can see it.
// Do note that this is optional; there's no harm in making it public.
private interface ITenantContextApplier {
void SetCurrentTenant(Tenant tenant);
}
private class AspNetTenantContext : ITenantContextApplier, ITenantContext {
// Implement both interfaces
}
private class BackgroundProcessingCommandHandlerDecorator<T> { ... }
public static Container Bootstrap(Container container) {
container.RegisterPerWebRequest<ITenantContext, AspNetTenantContext>();
container.Register<ITenantContextApplier>(() =>
container.GetInstance<ITenantContext>() as ITenantContextApplier);
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(BackgroundProcessingCommandHandlerDecorator<>));
}
}
A different approach would be to just make the complete ITenantContext available to the background thread, but to be able to pull this off, you need to make sure that:
The implementation is immutable and thus thread-safe.
The implementation doesn't require disposing, because it will typically be disposed when the original request ends.
How do I write this Entity Framework LINQ Query as a Compiled Query?
var context = new SlxDbContext();
var userSet = context.Set<User>();
User user = userSet.Where(x => x.UserName == "gstrader").First();
There's no way to use CompiledQuery when you're using the DbContext API; CompiledQuery works only with ObjectContext. If you're using Code First, you're most likely using the DbContext API. And Microsoft recommends that you use the DbContext API in new projects even if you'll be working with Database First or Model First models.
But if you use EF5, it brings auto-compiled queries, which work very differently than CompiledQuery. Instead of your writing code to compile each query and then invoking each as needed, EF5 caches the generated SQL for you as a background process, then searches the cache for already compiled queries when you execute any query.
See:
http://blogs.msdn.com/b/adonet/archive/2012/02/14/sneak-preview-entity-framework-5-0-performance-improvements.aspx
and
http://www.devproconnections.com/article/entity-framework/entity-framework-5-143875
Unfortunately the version of EF you are using (code first), does not support compiled queries.
Please correct me if I'm wrong.
Some links:
How do I precompile an Entity Framework Code-First Query?
EF Code First DbContext and Compiled Queries
http://blogs.msdn.com/b/adonet/archive/2011/03/02/ef-4-1-is-coming-dbcontext-api-amp-code-first-rtw.aspx
UPDATE:
Here is a sample for compiled queries, but I think it's not going to work with Code First:
public static Shop CompiledGetShopById(Guid shopId)
{
using (DataContext dtx = new DataContext(ConfigProvider.ConnectionString)) {
return Compiled_GetById.Invoke(dtx, shopId);
}
}
private static Func<DataContext, Guid, Shop> Compiled_GetById =
Objects.CompiledQuery.Compile<DataContext, Guid, Shop>(
(DataContext db, Guid shopId) =>
(from item in db.Shops where item.ShopId == shopId)
.FirstOrDefault()
);
Almost certainly a stupid question but I can't find the answer anywhere.
In the Getting Started tutorial the database is SQLite and so his session factory creation
is done using the SQLiteConfiguration class in the FluentNHibernate.Cfg.Db namespace
Great! But I don't see a Configuration class for using an Oracle database. How do I do this?
Cross-posted to the fluent NH mailing list (with answer)
This works for me. Hope this helps!
private static ISessionFactory CreateSessionFactory()
{
var cfg = OracleClientConfiguration.Oracle9
.ConnectionString(c =>
c.Is("DATA SOURCE=<<NAME>>;PERSIST SECURITY INFO=True;USER ID=<<USER_NAME>>;Password=<<PASSWORD>>"));
return Fluently.Configure()
.Database(cfg)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<CLASS_NAME>().ExportTo(#".\"))
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
private static void BuildSchema(NHibernate.Cfg.Configuration config)
{
// this NHibernate tool takes a configuration (with mapping info in)
// and exports a database schema from it
new SchemaExport(config)
.Create(false, true);
}
Does this helps you?
http://tiredblogger.wordpress.com/2008/12/04/persistanceconfiguration-for-oraclefluent-nhibernate/
Edit: The code mentioned uses the ConnectionStringExpression class which no longer exists in Fluent NHibernate. However, that class isn't used for anything other than holding the OracleConfiguration _config field. You can safely, add the field to the OracleConnectionStringExpression class and remove it.
The remaining issue is that NHibernate will now for some reason look for components that are not in the current build of Oracle.DataAccess. If you want to deal with that you can do what tiredblogger did here.