System.InvalidOperationException: A second operation started on this context before a previous operation completed in Blazor and EFCore - exception

I have method like the DeleteSettingAbout() after in text, where I am still getting error: "System.InvalidOperationException: A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.".
Code of the method is:
public async Task DeleteSettingAbout(int Id)
{
SettingAbout setting = await _context.SettingsAbout.FirstOrDefaultAsync(o => o.Id == Id);
if (setting != null)
{
_context.SettingsAbout.Remove(setting);
await _context.SaveChangesAsync();
}
}
In sartup.cs I set DBContext and DBRepository as Transient:
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("AppDBConnection")),
ServiceLifetime.Transient);
services.AddTransient<IAppDbRepository, SQLAppDbRepository>();
But I am still getting this error.
How to solve this behavior? Thanks for answers.
UPDATE 2021-01-06
I tried the approach with creating the "DbContextFactory" and it solved my problem. I got inspiration from sample app https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/blazor/common/samples/3.x/BlazorServerEFCoreSample (mentioned here: https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-3.1#sample-app-3x).
Now I have in my startup.cs this:
// new way suitable for Blazor - register factory and configure the options (new instance for each method call)
services.AddDbContextFactory<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("AppDBConnection")));
services.AddScoped<IAppDbRepository, SQLAppDbRepository>();

I tried the approach with creating the "DbContextFactory" (mentioned by Stephen Cleary) and it solved my problem. I got inspiration from sample app https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/blazor/common/samples/3.x/BlazorServerEFCoreSample (mentioned here: https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-3.1#sample-app-3x).
Now I have in my startup.cs this:
// new way suitable for Blazor - register factory and configure the options (new instance for each method call)
services.AddDbContextFactory<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("AppDBConnection")));
services.AddScoped<IAppDbRepository, SQLAppDbRepository>();
Note: I needed to solve the problem in EF/Blazor = v3.1 (because my web-hosting does not support v5 for now)
Thank you all for answers!

Related

Xamarin.Forms Plugin.Geofence giving System.InvalidCastException: Specified cast is not valid

I am using Plugin.Geofence i Implemented its interface,Installed its dependencies i.e. .NETStandard 2.0 and Xamarin.GooglePlayServices.Location.
I am getting this exceptions System.InvalidCastException: Specified cast is not valid. when i run StartMonitoring method.
I am calling this method in the App() Constructor.
public App ()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
CrossGeofence.Current.StartMonitoring(new GeofenceCircularRegion("MyRegion", 31.475085, 74.305833, 200)
{
//To get notified if user stays in region for at least 5 minutes
NotifyOnStay = true,
StayedInThresholdDuration = TimeSpan.FromMinutes(5)
});
}
Tried everything but couldn't resolve this
For anyone looking for a solution to this, ensure that before calling "CrossGeofence.Current" that the correct permissions have been requested and granted. If not, you'll see this error.

How do I use Castle Windsor to create a RavenDB session with client version > 3.0.3660?

I am using Castle Windsor v3.4.0 to create a RavenDB document session instance but when I use a RavenDB client version later than 3.0.3660 I get this error when calling the Store method:
Castle.MicroKernel.ComponentNotFoundException: 'No component for supporting the service System.Net.Http.HttpMessageHandler was found'
Here is the smallest piece code I can come up with that reproduces the error:
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Raven.Client;
using Raven.Client.Document;
public class Program
{
public static void Main()
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component
.For<IDocumentStore>()
.ImplementedBy<DocumentStore>()
.DependsOn(new { Url = "http://localhost:8081", DefaultDatabase = "Test" })
.OnCreate(x => x.Initialize())
.LifeStyle.Singleton,
Component
.For<IDocumentSession>()
.UsingFactoryMethod(x => x.Resolve<IDocumentStore>().OpenSession())
.LifeStyle.Transient);
using (var documentSession = container.Resolve<IDocumentSession>())
{
documentSession.Store(new object());
documentSession.SaveChanges();
}
}
}
Here's what I believe is happening. A change was made to the RavenDB client after v3.0.3660 that changed how the HttpMessageHandler is created in the HttpJsonRequest class:
https://github.com/ravendb/ravendb/commit/740ad10d42d50b1eff0fc89d1a6894fd57578984
I believe that this change in combination with my use of the TypedFactoryFacility in my Windsor container is causing RavenDB to request an instance of HttpJsonRequestFactory and it's dependencies from Windsor rather than using it's own internal one.
How I can change my code to avoid this problem so that I can use a more recent version of the RavenDB client?
Given your MVCE, Windsor is set up to inject object's properties. So, when creating the DocumentStore, Castle is trying to find a value for the HttpMessageHandlerFactory property and is failing since nothing is configured for that particular type.
I was able to get your example to work (at least, it got to inserting the data into my non-existing server) by just filtering out that property:
container.Register(
Component.For<IDocumentStore>()
.ImplementedBy<DocumentStore>()
.DependsOn(new { Url = "http://localhost:8081", DefaultDatabase = "Test" })
.OnCreate(x => x.Initialize())
.PropertiesIgnore(p => p.Name == nameof(DocumentStore.HttpMessageHandlerFactory))
.LifeStyle.Singleton);
Alternatively, if you have a value for it, you could add it to the object passed to DependsOn().

MVVMCross ViewModel construction failure notifications

We've noticed a couple of times in our mobile applications that users have reported the application hanging or seeming to become unresponsive between views / rare crashes when switching between views. We've tracked down these cases to when our view model constructors throw uncaught exceptions.
We want to put a solution in place so that if a view model fails to construct for some reason then we can notify the user and provide some message that will be useful to us when it's logged through support.
I've been taking a look at doing this but haven't found a reliable way to achieve this.
The first thing we tried was at the IMvxViewModelLocator level. We already have a custom implementation of IMvxViewModelLocator so we've modified this. We allow all exceptions to be thrown and then we have an IErrorHandler interface which each platform implements. We then call this to attempt to show a dialog. This has proved to be unreliable and the dialog does not always display. Something along the lines of: (note - here ResolveViewModel will always return true or throw)
public override bool TryLoad(Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState, out IMvxViewModel viewModel)
{
try
{
return ResolveViewModel(viewModelType, parameterValues, savedState, out viewModel);
}
catch (Exception exception)
{
_errorHandler.HandleViewModelConstructionException(viewModelType, exception);
viewModel = null;
return false;
}
}
What we would ideally like to do is intercept any failure to construct a view model and then re-request an ErrorViewModel. We've tried to do this 2 ways:
1)
We've tried defining a custom IMvxViewDispatcher for each platform and we're trying to intercept failures as below but if an exception in the constructor is thrown we never get back this far:
public class TouchDispatcher : MvxTouchUIThreadDispatcher, IMvxViewDispatcher
{
private readonly IMvxTouchViewPresenter _presenter;
public TouchDispatcher(IMvxTouchViewPresenter presenter)
{
_presenter = presenter;
}
public bool ShowViewModel(MvxViewModelRequest request)
{
Action action = () =>
{
_presenter.Show(request);
};
try
{
bool success = RequestMainThreadAction(action);
return !success ? HandleError() : success;
}
catch (Exception)
{
return HandleError();
}
}
// Other bits
}
2)
We thought we might have more success at the presenter level. We modified our ViewPresenter for each platform and we have overridden void Show(MvxViewModelRequest request). This has not proved to be successful either as exceptions don't propagate back this far.
This leaves me thinking that maybe we are better attempting this at the IMvxViewModelLocator level again.
Has anyone found a way to reliably intercept failures to construct view models and then ideally re-request a different view model / present some dialog to the user?
It seems you've identified that the core of the problem is when: "view model constructors throw uncaught exceptions."
This is going to be slightly problematic as the ViewModel's are generally constructed during View lifecycle overrides like ViewDidLoad, OnCreate or NavigatedTo - which is generally after the Presenter has finished requesting presentation.
As you've already found an easy place to identify when ViewModel construction has failed is in a custom IMvxViewModelLocator - others likeIMvxViewModelLoader are also possible. This is probably the easiest place to catch the error and to trigger the error handling - you can then get hold of the IMvxViewDispatcher (or presenter) there in order to change the display. However, you will still need to make sure your Views can handle null created ViewModels - as the ViewDidLoad, etc calls will still need to complete.

create a StreamSource with getClass().getClassLoader().getResourceStream(

I post this question and I got some explanations but I couldn't solve the problem. Now since event I have a better understanding I'm going to post this again in a new angle.
I have following lines in my node.
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
/*
* Associate the schema factory with the resource resolver, which is
* responsible for resolving the imported XSD's
*/
factory.setResourceResolver(new ResourceResolver());
Source schemaFile = new StreamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Schema schema = factory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.validate(new DOMSource(document));
I think I have two options. Either to mock
Source schemaFile = new StreamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
or
Schema schema = factory.newSchema(schemaFile);
I have been pulling my hair for two day to do the first one. I tried as follows
expectNew(StreamSource.class, InputStream.class).andReturn(mockSource);
and
expectNew(StreamSource.class, anyObject(InputStream.class)).andReturn(mockSource);
But didn't work.
Now I'm trying to mock the second line
Schema schema = factory.newSchema(schemaFile);
This one also not quite clear to me. Do I need to mock a factory like
SchemaFactory mockFactory = EasyMock.createMock(SchemaFactory.class);
or since factory is created using newInstance static method call is it a different way?
Appreciate any help on this problem.
Adding later
I got some lead with the situation. I have expectNew as follows.
expectNew(StreamSource.class, InputStream.class).andReturn(mockStreamSource);
When I run powermocks throws a error saying.
java.lang.AssertionError:
Unexpected constructor call javax.xml.transform.stream.StreamSource(null):
javax.xml.transform.stream.StreamSource(class java.io.InputStream): expected: 1, actual: 0
The reason is as I think getClass().getClassLoader().getResourceStream("..") return null anyway. So powermock didn't find it euqal to the initialization I describe by expectNew. How to say expect a null inputstream as parameter. I tried using just null. didn't work.
expectNew(StreamSource.class, null).andReturn(mockStreamSource);
If you're using easymock:
Extract the creation of the factory to a protected method.
protected SchemaFactory createSchemaFactory(){
return SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
}
In your test, instead of test the SUT itself create a partially mocked version of your SUT, mocking only the new method where the static invocation is done, and test it. Partial mocks using easymock.

Mailing Exception logs in a live Grails webapp

I'd like my Grails web-app to send an e-mail for each exception that reaches the end-user.
Basically I'm looking for a elegant way to achieve something equivalent to:
try {
// ... all logic/db-access/etc required to render the page is executed here ...
}
catch (Exception e) {
sendmail("exception#example.com", "An exception was thrown while processing a http-request", e.toString);
}
Turns out this exact question was answered on the Grails mailing list a couple of days ago.
The solution is to add the following to the log4j-section of Config.groovy:
log4j {
...
appender.mail='org.apache.log4j.net.SMTPAppender'
appender.'mail.To'='email#example.com'
appender.'mail.From'='email#example.com'
appender.'mail.SMTPHost'='localhost'
appender.'mail.BufferSize'=4096
appender.'mail.Subject'='App Error'
appender.'mail.layout'='org.apache.log4j.PatternLayout'
appender.'mail.layout.ConversionPattern'='[%r] %c{2} %m%n'
rootLogger="error,stdout,mail"
...
// rootLogger="error,stdout" (old rootLogger)
}
Plus adding sun-javamail.jar and activation.jar to the lib/-folder.
Assuming you can do this from groovy, you'll want to use a logging framework such as log4j for this, which has loggers that can append log data to a database, send email, etc.
You could also take a look at exceptionHandler mechanism provided by Grails; I find it very simple; yet powerful enough to take care of all my custom & clean exception handling needs. Haven't tested this approach with 1.1 so far; but works very well with 1.0.3.
class BootStrap {
def exceptionHandler
def init = { servletContext ->
exceptionHandler.exceptionMappings =
[ 'NoSuchFlowExecutionException' :'/myControler/myAction',
'java.lang.Exception' : '/myController/generalAction']
}
def destroy = { }
}
Detailed blog here :
http://blog.bruary.net/2008/03/grails-custom-exception-handling.html