How do I setup SharpRepository to work with AutoFac & Entiry Framework? - entity-framework

I have installed
SharpRepository.EfRepository
SharpRepository.Ioc.Autofac
SharpRepository.Repository
and I have added this code to setup Autofac as instructed by the Autofac documentation:
void SetupAutofac()
{
var builder = new ContainerBuilder();
// Get your HttpConfiguration.
HttpConfiguration config = GlobalConfiguration.Configuration;
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac filter provider.
builder.RegisterWebApiFilterProvider(config);
// Set the dependency resolver to be Autofac.
IContainer container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
but the SharpRepository getting started guide doesn't help me with the Autofac --> EF --> SharpRepo glue stuff as it's oriented towards StructureMap. Please advice!
(I'd like to avoid putting stuff in Web.config if possible)

You will need to install the SharpRpository.Ioc.Autofac NuGet package, if you haven't.
Then you will call
builder.RegisterSharpRepository()
in order to tell Autofac how to handle an IRepository.
Then to tell SharpRpository to use Autofac when it needs EF you will need to call
RepositoryDependencyResolver.SetDependencyResolver(new AutofacDependencyResolver(container));
That should do it.

Related

Autofac IContainer and DiagnosticTracer for ASP .Net 5

How I can get IContainer instance for my ASP.Net 5 app?
I need to enable diagnostics, and based on official documentation SubscribeToDiagnostics method is accessible only from IContainer, and ASP Net Core 3+ Integration this.AutofacContainer = app.ApplicationServices.GetAutofacRoot(); exposes only ILifetimeScope.
I have also noticed that Autofac supports DiagnosticListener - is this a way how I should trace for informations?
Does Autofac provide build in formatters for example for RequestDiagnosticData?
What are your recommendations?
I've updated the ASP.NET Core 3 example for Autofac to show how this works. The secret is using a build callback.
In your ConfigureContainer method, you register a callback to subscribe to diagnostics.
public void ConfigureContainer(ContainerBuilder builder)
{
// Add any Autofac modules or registrations, then...
//
// If you want to enable diagnostics, you can do that via a build
// callback. Diagnostics aren't free, so you shouldn't just do this
// by default. Note: since you're diagnosing the container you can't
// ALSO resolve the logger to which the diagnostics get written, so
// writing directly to the log destination is the way to go.
var tracer = new DefaultDiagnosticTracer();
tracer.OperationCompleted += (sender, args) =>
{
Console.WriteLine(args.TraceContent);
};
builder.RegisterBuildCallback(c =>
{
var container = c as IContainer;
container.SubscribeToDiagnostics(tracer);
});
}

In Slim Framework, what is a container and what is it for?

I am new to Slim Framework.
There is this dependency container.
What is that?
How is it used?
And can we avoid or not use that?
Slim uses a dependency container to prepare, manage, and inject application dependencies. Unlike its previous version, Slim 4 no longer ships with or depends on a dependency container to work and is now totally optional. If you decide your application requires one, you need to bring it in yourself provide an instance of it to AppFactory before creating your App.
I personally use League Container
$container = new League\Container\Container;
Slim\Factory\AppFactory::setContainer($container);
$app = Slim\Factory\AppFactory::create();
You add dependencies to your container like so;
$container->set('myService', function () {
$myService = new MyService();
return $myService;
});
which then allows you to fetch dependencies from your container from inside a Slim application route like this:
$app->get('/foo', function (Request $request, Response $response, $args) {
$myService = $this->get('myService');
// ...do something with $myService...
return $response;
});
You can read the current docs for v4 here

Web Api OData v4.0 and Memory Usage/Leak with Castle Windsor

I have a web project which is configured to provide an OData v 4.0 endpoint and is using the following components:
ASP.NET Web Api 5.2.2
Entity Framework 6.1.1
Owin 5.2.2
OData 5.3.1
The entire web application is using Windsor container from Castle Project.
The lifestyle of my controllers is per web request and same applies for all dependencies including DbContext.
The IoC is configured as following:
Owin Startup .cs
WindsorConfig.InitializeContainer(GlobalConfiguration.Configuration);
Configuration.cs
IWindsorContainer container = new WindsorContainer();
container.Install(FromAssembly.This());
container.Register(Component.For<IWindsorContainer>().Instance(container));
config.DependencyResolver = new WindsorDependencyResolver(container);
Installer.cs
container.Register(FromAssembly.This()
.BasedOn<ODataController>()
.LifestylePerWebRequest());
container.Register(
Component
.For<DbContext>()
.ImplementedBy<MyContext>()
.LifestylePerWebRequest());
So, an OData controller looks like this:
public class PersonsController : ODataController
{
#region Public Constructors
public PersonsController(ICommandDispatcher commandDispatcher, DbContext session)
{
this.commandDispatcher = commandDispatcher;
this.session = session;
}
public IQueryable<Person> Get()
{
return session
.Set<Person>()
.AsNoTracking();
}
public SingleResult<Person> Get([FromODataUri] Guid key)
{
return SingleResult.Create(session
.Set<Person>()
.AsNoTracking()
.Where(x => x.Id == key));
}
}
I am using Set.AsNoTracking() to avoid extra memory usage from Entity Framework.
Anyway, during time, after 100/150 queries the memory of the app pool keep raising of 1-2 MB and it never gets recycled.
Am I doing something wrong? Maybe Castle is not appropriate for this project and I have to use another IoC container?

using filters with autofac in webapi2

I have a actionfilter something as below.. The filter basically adds a few attributes to the header of the response..
public class myHeaderAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Response != null)
//my code goes here
base.OnActionExecuted(actionExecutedContext);
}
}
I would normally call this in WebApiConfig.Register as config.Filters.Add(new myHeaderAttribute());
I wish to use Autofac in my project..
There is a page in autofac site (http://docs.autofac.org/en/latest/integration/webapi.html)which speaks of implementing IAutofacActionFilter.
But, I'm not very clear as to what I'm supposed to do.
I can create another class which implements IAutofacActionFilter and add the onActionExecuted method.
But do I also keep my present class or remove it along with the line in WebApiConfig.Register.
Also the page speaks of registering the Autofac filter provider as well as the class which implements IAutofacActionFilter. But no complete example exists.
Also, it speaks of using 'service location' in case we need per-request or instance-per-dependency services in our filters.
The whole thing seems a little too confusing to me. I would sincerely appreciate if someone who understands these concepts and has used Autofac in a web api2 project could guide me.
Thanks
Remove it. It explains exactly in the docs you reference yourself that it uses its own action filter resolver. See section "Provide filters via dependency injection".
Update
First register the filter provider:
var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(config);
Then register your actionfilter like so:
builder.Register(c => new myHeaderAttribute())
.AsWebApiActionFilterFor<YourController>(c => c.YourMethod(default(int)))
.InstancePerApiRequest();
So complete code:
var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(config);
builder.Register(c => new myHeaderAttribute())
.AsWebApiActionFilterFor<YourController>(c => c.YourMethod(default(int)))
.InstancePerApiRequest();
It's all right there in the docs. If you have any specific question then you can ask seperately. But this is becoming to be too broad.

EF + UnitOfWork + SharePoint RunWithElevatedPrivileges

In our SharePoint application we have used the UnitOfWork + Repository patterns together with Entity Framework. To avoid the usage of the passthrough authentication we have developed a piece of code that impersonate a single user before creating the ObjectContext instance in a similar way that is described in "Impersonating user with Entity Framework" on this site.
The only difference between our code and the referred question is that, to do the impersonation, we are using RunWithElevatedPrivileges to impersonate the Application Pool identity as in the following sample.
SPSecurity.RunWithElevatedPrivileges(delegate() {
using (SPSite site = new SPSite(url)) {
_context = new MyDataContext(ConfigSingleton.GetInstance().ConnectionString);
}
});
We have done this way because we expected that creating the ObjectContext after impersonation and, due to the fact that Repositories are receiving the impersonated ObjectContext would solve our requirement.
Unfortunately it's not so easy. In fact we experienced that, even if the ObjectContext is created before and under impersonation circumstances, the real connection is made just before executing the query, and so does not use impersonation, which break our requirement.
I have checked the ObjectContext class to see if there was any event through which we can inject the impersonation but unfortunately found nothing.
Any help?
We had a simillar problem when we used LinqToSharePoint. The DataContext is created from the HttpContext.Current and did not consider the RunWithElevatedPrivileges method. We did a nasty workaround that we backed up the original HttpContext, created a new dummy HttpContext in the RunWithElevatedPrivileges method and the problem went away. Obviously we set the context to the original afterwards.
Edit:
You can use the method below to create new dummy HttpContext.Call this method as first in your RunWithElevatedPrivileges. In the normal context just backup your currenct context with var backupContext = HttpContext.Current and after everything is done just set the context back.
private void SetNewContextWeb(SPWeb oWeb)
{
HttpRequest httpRequest = new HttpRequest(string.Empty, oWeb.Url, string.Empty);
HttpContext.Current = new HttpContext(httpRequest, new HttpResponse(new System.IO.StringWriter()));
SPControl.SetContextWeb(HttpContext.Current, oWeb);
}