I created a .net 6 minimal API project with EF Core that uses DI to create repositories with Scoped lifetime. The API project uses mediatr to send the request to a proper handler. The handler's get injected with db repositories. This works when I run this project directly.
I am migrating that project to an AWS Lambda project using the new AWS .NET 6 Templates in the visual studio toolkit. For whatever reason, the exact same code that runs fine in the minimal API project now throws an error because the injected repositories dispose their connections before the end of the request.
This error occurs anytime I run a command against the database.
I believe this is happening because of a serialization error that occurs in entity framework core. This issue doesn't occur in my regular project because I'm guessing it's using a different serializer to handle the serialization of entities.
The errors being thrown are:
System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.
Cannot access a disposed context instance
If I update the Json Serializer that .net is using to handle cycles, then the 1st error turns into: "System.NotSupportedException: Serialization and deserialization of 'System.Type' instances are not supported".
This looks like some sort of conflict with Pomelo Entity Framework Core
and the way the .net 6 lambda templated project is setup.
EDIT:
After looking at this more, I think the issue is with whatever serialization library that AWS Lambda template project uses vs whatever serialization library is normally used by Pomelo to handle things.
Related
A conceptual question for vdm usage. Assume my OData evolves in a S4 cloud system and I am consuming it in a microservice. Since vdm needs the edmx file to generate entitiy classes, assume my odata has a new field or has eliminated one field that I do not use. If I do not change my edmx and will not generate new classes, will it be still work my call? And second question is, if one of the fields I use change, and I need to ensure 0 downtime, how do I handle 2 versions of generated classes in the same time?
The generated OData VDM ultimately performs an OData call based on the fields that are used. So if you would not use fields that are removed, this should not be a problem. Note however, that such removals would have to be done in a new version of the SAP S/4HANA service.
Since breaking changes affect all consumers independent of whether the Java or JavaScript VDM of the SAP S/4HANA Cloud SDK is used, developers of services in SAP S/4HANA have to follow a certain API guideline that includes specific deprecation rules.
So, if a breaking change is really required, according to the S/4HANA API guideline, a new version of the service has to be published and this will be also available with a different URL. This then gives you the possibility to migrate from an old to a new version without interruptions.
I can find a lot of articles on how to enable DbContextPooling in ASP Net Core through AddDbContextPool function.
But what about .Net framework 4.7.2 when this is not available. How can I reuse the DbContext from the pool?
Thanks
AddDbContextPool sets up services in the dependency injection container to make it more efficient to get DbContext instances for each request.
If you are not using ASP.NET Core, but your application follows a similar model (e.g. DbContext instances are needed to process Web or service requests) and the number of requests per second is very large, then my first recommendation would be to setup DI using Microsoft.Extensions.DependencyInjection and create DI scopes per request like ASP.NET Core does. Once you do that, you should be able to call AddDbContextPool the same way you would do in an ASP.NET Core application, and resolve your DbContext using DI with all the benefits of DbContext pooling.
Besides that option, in theory you could do manually what AddDbContextPool achieves using DI.
For example, first create a singleton pool of type DbContextPool. Then, for every instance of YourDbContext you need, get a lease using pool.Lease, and then get the context using lease.Context.
You have to make sure that you dispose both the context and the lease when you are done using them.
Caveat: this approach requires direct usage of low level APIs that are in internal namespaces and that therefore could change or disappear in any future minor or major release of EF Core.
If your application doesn't work like that (for example, if it is not a web application or a web service that need to process large numbers of requests), then there is no advantage on using DbContext pooling.
Scenario: the application has a long running method to return the data and build the final entity of a slowly changing dimension. In the previous versions of .net the data could be setup for interception and caching with the CacheInterceptionBehavior while registering the Interface with Unity.
Is there a corresponding way to do something similar in .net core?
We currently have two different applications consuming our OData, WCF Data Service
We want to add a third application, but this one, rather than being a website, is another WCF Data Service. It is effectively a subset of functionality, exposing some methods from the internal service to as a public api.
As soon as I add a reference from one WCF Data Service to another, I end up in a conflict between System.Data.Services in the GAC and Microsoft.Data.Services implementations of DataService.
Is there a proper way to create an OData WCF Data Service wrapper for another OData WCF Service?
This is the error
Error 1 Reference.datasvcmap: The type
'System.Data.Services.Client.DataServiceCollection`1' is ambiguous: it
could come from assembly 'D:\source...\bin\Microsoft.Data.Services.Client.DLL' or from
assembly 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Data.Services.Client\v4.0_4.0.0.0__b77a5c561934e089\System.Data.Services.Client.dll'. Please specify the assembly explicitly in the type
name. App_WebReferences/WcfDataService/
Not sure it has to do with the wrapping (may just be a side-effect from the way you set it up in Visual Studio). Try removing the reference to System.Data.Services.Client.dll, I believe the OOB NuGet packages are favored.
In MVC, a ModelValidatorProvider is instantiated and called to validate a model on each request. This means that in a DI environment, it can take dependencies on objects scoped within a single request, such as a Unit of Work or Database context. In Web API, this appears to have been significantly changed. Instead of being instantiated per-request, the ModelValidatorProvider appears to be long-lived and instantiated within the application startup. The WebAPI then caches the results from the ModelValidatorProvider per-type, meaning that the ModelValidator cannot take any dependencies from DI.
I am trying to implement my ModelValidator to use a factory using a Service Locator (please, no automatic 'anti-pattern' comments!). This would allow me to construct an internal validator object within each request, which would be able to take dependencies from the container. However, I cannot get hold of a Dependency Resolver or container scoped to the current request from within this ModelValidator which is essentially scoped as a Singleton. I've tried to use GlobalConfiguration.Configuration.DependencyResolver, but this only returns globally-scoped services (from the root scope, also mentioned here)
I'm working in Autofac, so an autofac-specific solution would be suitable (e.g. MVC has AutofacDependencyResolver.Current, which internally uses DependencyResolver.GetService). There is no equivalent available in the WebAPI integration, presumably because of the reason mentioned above where the global DependencyResolver only returns globally-scoped services.
The reason I'm trying to do this (as well as for my own use) is to implement the Web API integration for FluentValidation, which currently does not exist. There have been two attempts so far, but neither of these handle the Dependency Injection issue and instead result in a single static ModelValidator.
Things I've tried so far:
Using GlobalConfiguration.Configuration.DependencyResolver (returns objects from the root scope)
Taking a dependency on Func<IComponentContext> (always returns the root context)
In an answer which has since been removed, it was suggested to remove IModelValidatorProvider service from the Web API config. This had to be done using reflection since the interface and the implementing classes are all defined as internal, but it did make the validators work better (because the ModelValidator was constructed per request). However, there is a significant performance hit to doing it this way due to the use of reflection to check for validators on the model and every property it has, so I don't want to take this option.
Filip W's answer suggests using HttpRequestMessage to get the Dependency Scope, but I've not found anything such as HttpRequestMessage.Current which would provide access to this object from within a long-lived object - if that could be achieved I believe everything would fall into place.
To get current dependency scope, you have to use (surprise, surprise :) GetDependencyScope() of the current HttpRequestMessage (more about which you can read up on MSDN) instead of GlobalConfiguration.
I blogged about Web API per-request dependency scope a while ago - that should be helpful.