I am using a MVC4, C#, Castle Windsor, fluentnhibernate stack for my web application, which generally works very well.
Its only occasionally that I get an error related to nHibernate something along the lines of:
Invalid attempt to call Read when reader is closed.
or
Internal connection fatal error.
This usually rears its ugly head when I do multiple calls, in very close succession.
Currently I am replicating it while doing multiple ajax gets, from JQuery.
What I suspect the problem is, is with my NHibernate session management.
The only thing I can think of is that the calls are someone using the same session, the first one completes and closes it, then the following call is unable to complete.
This shouldn't be possible due to the way my sessions are handled like this:
Kernel.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(_ => config.BuildSessionFactory()),
Component.For<ISession>()
.UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
.LifestylePerWebRequest());
Should be one session per request right?
How else, or where else can I look for the problem? I am quite stuck.
Of course solved this a few minutes later, but the answer was an eye opener for me.
This answer led me down the right path.
While all of my Repositories, Manager and other layers were installed with the correct lifestyle using Castle Windsor, there was one that wasn't.
I was doing a Repository call from an ActionFilter, all of my action filters are invoked through an ActionInvoker class which was registered incorrectly as Singleton, which resulted in my errors.
container.Register(Component.For<IActionInvoker>()
.ImplementedBy<WindsorActionInvoker>()
.LifeStyle.***Singleton***);
Should of course be
container.Register(Component.For<IActionInvoker>()
.ImplementedBy<WindsorActionInvoker>()
.LifeStyle.Transient);
Just another reminder to pay closer attention to those Lifestyles.
Related
I have a large >10 year old web app which I'm gradually upgrading to Entity Framework 7, .Net 7 and ASP.Net Core. I'm in the middle of this big piece of tech debt payoff. I think (hope) I'm about 80% done... So there's only the other 80% to do :-).
One unexpected migration step I just ran into, is that System.Diagnostics.Trace doesn't work with the modernized ILogger logging/tracing infrastructure in .NetCore/Asp.NetCore. I have 100s of System.Diagnostics.Trace calls spread across all the projects involed in this solution, and across several layers of business logic classes. I would prefer to avoid figuring out how to pass the ILogger objects around through dependency injection and (I'm guessing this'll be required in some places) changing new/create calls and constructors to pass it in.
So I found a promising approach to be able to postpone the migrating from System.Diagnostics to ILogger. Thanks to a few people who blazed this trail before me, there are some great ideas:
https://www.codeproject.com/Articles/5255953/Use-Trace-and-TraceSource-in-NET-Core-Logging
and
https://khalidabuhakmeh.com/logging-trace-output-using-ilogger-in-dotnet-applications
I went with this approach, creating a TraceListener which I add to System.Diagnostics.Trace, and which sends all the logging calls to an ILogger.
// Set up trace/debug logging.
IServiceCollection serviceCollection = builder.Services.AddLogging(iLoggingBuilder =>
{
iLoggingBuilder
//.ClearProviders()
//.AddConsole()
//.AddEventLog()
//.AddEventSourceLogger()
.AddConfiguration(builder.Configuration.GetSection("Logging"));
});
...
// Make the Asp.Net Core Logging framework listen to what comes from the System.Diagnostics.Trace framework, since that old tracing framework is what our DB+Model project uses.
ILogger<Program> logger = app.Services.GetRequiredService<ILogger<Program>>();
//ILogger<Program> logger = app.Services.GetService<ILoggerFactory>().CreateLogger<Program>();
Trace.Listeners.Clear();
Trace.Listeners.Add(new LoggerTraceListener(logger));
The LoggerTraceListener implementation I have is very similar to what is shared here:
https://www.codeproject.com/Articles/5255953/Use-Trace-and-TraceSource-in-NET-Core-Logging
That works great. Except... Inside the Microsoft.Extensions.Logging code in .Net Core, the logging framework calls System.Diagnostics for its own logging. This results in an infinite loop. Every call I make to System.Diagnostics, is passed on to ILogger, and once it gets to Microsoft.Extensions.Logging, another System.Diagnostics call is made, which ends up back in my TraceListener.
I can fix this with a big hammer: adding ".ClearProviders()" as I set up the ILoggingBuilder. I can add back some of the default providers. If I leave ".AddDebug()" out, the logging from Microsoft.Extensions.Logging stops, so the issue is resolved. But I'd hate to stop all Debug logging - who knows what other parts of .Net and ASP.Net Core uses this. I'll become blind to some perhaps useful debug logging in the future. I'd rather avoid that.
I've tried stopping the loop by setting the appsettings.json logging level for Microsoft.Extensions.Logging to "Error", but it seems that only filters what is written out to the log, and doesn't stop the looping.
What could I do to stop the calls from Microsoft.Extensions.Logging from proceeding when those calls reach the methods in LoggerTraceListener? Is there another approach that'll fix this more reliably?
Or should I just resign to the fact that I need to add the System.Diagnostics->ILogger migration work to the long list of tech debt payoff I'm chewing through?
Update 1:
I tried two new approaches, still without success. One was to try the System.Diagnostics TraceFilter. Perhaps I could filter out the logging calls which cause the infinite loop? But that didn't work out. The TraceFilter for some reason doesn't get invoked on Trace.Write and WriteLine calls.
Then I tried looking up the callstack when the calls get to LoggerTraceListener. That'll probably work. But it'll cause a significant perf issue. For every trace call throughout the codebase, I'd then be walking the callstack... Not a good idea.
Update 2:
I gave up on trying to keep the System.Diagnostics.Trace calls unchanged in this code base. I started injecting and propagating ILogger instead. It's painful, especially lots of classes down in other projects can't be handled with dependency injection (without terrible 'separation of concern' impact), so I ended up passing an ILogger object around with the 'wrong' <T>.
I have a challenge using AWS Neptune WebSocket connections in lambda.
The problem is whenever an execution context is created even if I register the connection factory as Singleton in DI you will just get another instance for that execution context. With multiple limitations in such a connection like a machine type of your choice with a certain amount of connections and MaxInProcessPerConnection and ConnectionPoolSize, it won't take long enough to start seeing weird errors like System.Net.WebSockets.WebSocketException.
While I implemented some ping-alive connection hack-around it still is not great (and polluting the code too) I thought to somehow use the ILambdaContext by creating a custom inherited type with a static public property where you can access the connection factory and reuse the connections.
My problem is I can't even find anything for C# yet, something similar has been achieved in this Rust runtime GitHub discussion but I can't seem to understand how to translate it to C#.
This is an ASP.NET Core 6 API project running as lambda function.
Any suggestions on where to start will be highly appreciated.
I'm working on adding push notification into my ASP.NET core 2.0.0 webApp. I want to have a notification service that would have a badgeCount member which I would update when I send out notifications or when I mark something as read.
I wanted to make this a singleton, but it seems like I can't use dependency injection for singletons. I need access to my dbContext and maybe some other Identity /or Entity services later.
Would it make sense for me to make my notifcation service a scopedService instead of a singleton so that I can use DI? Then have a notificationBadge singleton that I would inject into my scopedService so I can maintain it?
I'm doing this so that I don't have to calculate the badge count each time (involves using queries)
EDIT: Actually, after writing this I realized that singletons are probably only instantiated once on server startup and not per user. So my initial approach wouldn't work even if I could use DI. I'd probably have to add a field on my user class that extends the IdentityUser then right? Or is there a way around this so that I don't have to update/save this to any db record?
Understanding DI
So to try and cover your question DI is certainly what you want in terms of most things inside your application and website. It can do singletons, as well as scoped and transcients (new copy every time).
In order to really understand DI and specifically the .Net Core implenentation I actually make use of the DI from .Net Core in a stand-alone .Net Standard open source library so you can see how it is done.
Video explaining the DI and showing me make and use the DI outside of ASP.Net Core scene: https://www.youtube.com/watch?v=PrCoBaQH_aI
Source code: https://github.com/angelsix/dna-framework
This should answer your question regarding how to access the DbContext if you do not understand it already from the video above: https://www.youtube.com/watch?v=JrmtZeJyLgg
Scoped/Transcient vs Singleton
What you have to remember when it comes to whether or not to use a singleton instance is singletons are always in-memory, so you should always consider and try to make things scoped or transcient to save memory, if the creation of that service is not intense or slow. So it is basically a trade off between RAM usage vs speed on some generate grounds.
If you then have specific types of service the decision becomes a different one. For example for DbContext objects you can think of them like a "live, in-memory database query/proxy" and so just like SQL queries you want to create them, execute them and be done with them. That is why they are made scoped, so that when a controller is created (per request) a new DbContext is created, injected, used by an action and then destroyed.
I guess the simple answer is it doesn't usually matter too much and most applications won't have any major concern or issues but you do have to remember singletons stay in-memory for the lifecycle of your application or the app domain if you are in a rare multi-domain setup.
Notification Count
So the main question is really about badges. There are many things involved in this process and setup, and so I will limit my answer to the presumption that you are talking about a client logged into a website and you are providing the website UI, and want to show the badge count for, and that you are not on about for example some Android/iOS app or desktop application.
In terms of generating the badge count it would be a combination of all unread messages or items in your database for the user. I would do this calculation on request from the user visiting a page (So in an Action and returned to the view via Razer or ViewBag for example) that needs that information, or from requesting it via Ajax if you are using a more responsive/Ajax style site.
That again I presume is not an issue and I state it just for completeness and presumptions.
So the issue you are asking about is basically that every time the page changes or the badge count is re-requested you are concerned about the time in getting that information from the database, correct?
Personally I would not bother trying to "cache" this outside of the database, as it is a fast changing thing and you will likely have more hit trying to keep the cache in-sync than just calling the database.
Instead if you are concerned the query will be intensive to work out the badge count, I would instead every time any addition to the database of an unread/new item, or a marking of an item as read is done, you do a "SetUnreadCount" call that calculates and writes that value as a single integer to the database so your call to get the unread count is a Scalar call to the database and SUPER quick.
Identity requires me to use this to create a db context:
app.CreatePerOwinContext(EFDbContext.Create);
So I need to get the Microsoft Unity IOC correct.
The issue I was coming across was that I had accidently made 2 database contexts. One for everything else in my application and one for the user stuff. I started writing functions for the user stuff under the wrong context and made it throw errors.
So I decided to use a lifetime manager for my EFDbContext:
// Database context
container.RegisterType<EFDbContext>(new PerThreadLifetimeManager());
// Microsoft identity stuff
container.RegisterType<ApplicationSignInManager>();
container.RegisterType<ApplicationUserManager>();
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(
new InjectionConstructor(typeof(EFDbContext)));
I am wondering if this will cause issues in the future?
Edit:
I found out that the asynchronous stuff in Identity might have been causing an issue with this set up...
I have now used HierarchicalLifetimeManager, it reads like the kind of thing I need... Still unsure if i'm going to come across any issues?
you should be ok - when you do a Resolve or ResolveAll to get the object back from the container and when you are set on using PerThreadLifeTimeManager then Unity will return the same instance for that thread. So unless you are doing multithreaded apps, then you should be fine.
ref: https://msdn.microsoft.com/en-us/library/ff660872(v=pandp.20).aspx
I found this article which seemed to do exactly what was needed:
http://www.wiktorzychla.com/2013/03/unity-and-http-per-request-lifetime.html
It has a request lifetime instead of thread or container... I was noticing odd problems when using hierarchical and this second one seems to work a charm!
On my quest to learn NHibernate I have reached the next hurdle; how should I go about integrating it with StructureMap?
Although code examples are very welcome, I'm more interested in the general procedure.
What I was planning on doing was...
Use Fluent NHibernate to create my class mappings for use in NHibs Configuration
Implement ISession and ISessionFactory
Bootstrap an instance of my ISessionFactory into StructureMap as a singleton
Register ISession with StructureMap, with per-HttpRequest caching
However, don't I need to call various tidy-up methods on my session instance at the end of the HttpRequest (because thats the end of its life)?
If i do the tidy-up in Dispose(), will structuremap take care of this for me?
If not, what am I supposed to do?
Thanks
Andrew
I use StructureMap with fluent-nhibernate (and NH Validator) in 3 of my current projects. 2 of those are ASP MVC apps and the third is a WCF web service.
Your general strategy sounds about right (except you won't be making your own Session or SessionFactory, as was already pointed out in comments). For details, snag my configuration code from here:
http://brendanjerwin.github.com/development/dotnet/2009/03/11/using-nhibernate-validator-with-fluent-nhibernate.html
The post is really about integrating NH Validator and Fluent-NHibernate but you can see exactly how I register the session factory and ISession with StructureMap in the "Bonus" section of the post.
RE: Tidy up: You should try and always work within a transaction and either commit or roll-back the transaction at the end of your unit of work. NH only utilizes SQL Connections when it needs them and will take care of the cleanup of that limited resource for you. Normal garbage collection will take care of your sessions themselves.
The Session Factory is a very expensive object that you will want to only initialize once and keep around for the life of your app.
I've not used structure map but maybee I can still help guide you in the right direction. Fluent nHibernate is awsome good choice over the hbm files.
As for the http request, you do not need to ensure that you close the session when the http request ends. If you don't you'll end up leaking nHibernate session. I'm not sure if structure map will handle this for you, what I've done is I have an http module which closes the session.
One thing to note though that bite me, is that you will make to sure you wrap all your data access in a transaction and ensure nHibernate actually commits its changes. If you do this as part of your session close, you could miss the chance to handle errors. I'm curious to hear what you ended up having to do to get this workign.