I am having a orchestration which will call a static method in a static class. I just discovered that if you need to run a Linq query a lot of times it is a good idea to make it into a compiled query. And my orchestration will be spawned a lot of times.
But im not sure I will win anything by making it into a compiled query.
Will each orchestration has to compile the query or will it be shared?
Each orchestration will execute on it's own thread so each orchestration will have it's own copy of the method's local variables including the linq query. So the query will be compiled every time the method is called.
Not sure how you can get around this, because the lifetime of the static class is determined by the lifetime of the orchestration. You could implement a singleton orchestration which could then call a non-static method. That way you could have the first call compile the query and all subsequent calls use the same query.
Related
Background (TLDR: I need parallel queries)
I am building REST service that needs to be able to answer queries very fast.
As such I'm pre-loading a large part of the database into memory and answering using that data instead of making complex database queries for each request. This works great, and the average response time of the API is well below the requirements and a lot faster than direct database queries.
But I have a problem. The service takes about 5 minutes to start and pre-load all of its information. During this time it can not answer queries.
Problem
I want to change this so that during the pre-load phase it makes database queries until the in-memory cache is loaded.
This leads me to a problem. I need to have multiple active queries to my database. Anyone who has tried this in EF Core has problably seen this message.
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.
The first sentence on the linked page is
Entity Framework Core does not support multiple parallel operations
being run on the same DbContext instance.
I thought this would be easily solved by wrapping my cache-loading into its own class and the direct query into another, and then having both of these requiring their own instance of the Database Context. Then my service can in turn get these injected and use both of these dependencies in parallel.
This should be what I have:
I have also set up my database context so that it uses transient for all parts.
services.AddDbContext<IDataContext, DataContext>(options =>
options.UseSqlServer(connectionString), ServiceLifetime.Transient, ServiceLifetime.Transient
);
I have also enabled MultipleActiveResultSets=True
All of this however results in the exact same error as listed above.
Again, everything is Transient except the HandlerService which is Singelton as I want this to keep a copy of the cache in memory and not have to load it for every request.
What is it I have failed to understand about the ef-core database context, or DI in general?
I figured out what the problem was. In my case there is as described above, one singleton handler. This handler has one (indirect) context (through DI) for fulfilling requests until the cache is loaded. When multiple parallel queries are sent to the API before the cache is loaded, then this error occurs as each of these request are using the same context. And in my test I was always hitting the parallel requests as part of the startup and hence the singelton service was trying to use the same db context for multiple requests. My solution is to in this one place step outside the "normal" dependency injection and use the IServiceScopeFactory to get a new instance of the dependency used to resolve requests before the cache is loaded. Bohdans answer led me to this conclusion and ultimate solution.
I'm not sure whether it qualifies for a full answer but it's too broad for a comment.
When doing .NET core background services which are obviously singletons too I use IServiceScopeFactory to create services with a limited lifetime.
Here's how I create a context
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<DbContext>();
}
My guess is that you could inject it in your hander and use it like this too. So it would allow you to leave context as scoped instead of transient with is default setting btw.
Hope that helps.
I'm writing web services in C++/CLI (not my choice) using Microsoft's Web API. A lot of functions in Web API are async, but because I'm using C++/CLI, I don't get the async/await support of C# or VB. So the fallback position is to use ContinueWith() to schedule a continuation delegate for reading the async task's result safely.
However, because C++/CLI also doesn't support inline anonymous delegates or managed lambdas, every delegate continuation must be written as a separate function somewhere. That quickly turns into spaghetti with the number of async functions in Web API.
So, to avoid the deadlock issues of Task<T>::Result, I've been trying this:
[HttpGet, Route( "get/some/dto" )]
Task< SomeDTO ^ > ^ MyActionMethod()
{
return Task::Run( gcnew Func< SomeDTO ^ >( this, &MyController::MyActionMethod2 ) );
}
SomeDTO ^ MyActionMethod2()
{
// execute code and use any task->Result calls I need without deadlocking
}
Okay, so I know this isn't great, but how bad is it? I don't yet understand enough of the guts of Web API or ASP.NET to comprehend the performance or scaling ramifications this will have.
Also, what other consequences may this have that aren't necessarily related to performance? For example, exceptions get wrapped in an extra AggregateException, which represents additional complexity and work for handling exceptions.
Your memory usage will increase with your application's parallelism. For every concurrent call to MyActionMethod you will need a separate thread with its own stack. That will cost you about 1 MB of RAM for each concurrent call. If MyActionMethod runs long enough so that 10000 instances run at once, you're looking at 10 GB of RAM. There is also CPU overhead in setting up each thread.
If concurrency is low, dropping async support won't be a problem. In that case, don't bother with Task::Run. Just change MyActionMethod to return SomeDTO^ (no Task wrapper).
Another potential concern is that lose easy use of cancellation tokens. However, for Web API it's usually fine to just let an exception propagate back to Web API, which ends up cancelling the synchronous call anyway.
Finally, if you were planning on performing any operation within your action method in parallel, you'll still need to use ContinueWith to accomplish that. Going non-async by default means you'll always perform one operation at a time. Fortunately, it's often just fine to do so.
Okay, so I know this isn't great, but how bad is it?
It's difficult to answer this without load-testing your specific scenario. But you can walk through the known semantics (taken largely from my blog).
First, when a request comes in, ASP.NET executes your handler on a thread pool thread within that request context. Your request handler calls Task.Run, which takes another thread from the thread pool and executes the actual request logic on it. The handler then returns the task returned from Task.Run; this releases the original request thread back to the thread pool.
Then, the Task.Run delegate will block on any asynchronous parts. So, this pattern has the scaling disadvantages of a regular synchronous handler, plus an extra thread context switch. Also, it uses a thread from the ASP.NET thread pool, which is not necessarily a bad thing, but in some scenarios it may throw off the ASP.NET thread pool heuristics.
Also, what other consequences may this have that aren't necessarily related to performance? For example, exceptions get wrapped in an extra AggregateException, which represents additional complexity and work for handling exceptions.
Yes, the exceptions from any .Result or Wait() calls will be wrapped in AggregateException. You may be able to avoid this by calling .GetAwaiter().GetResult() instead.
Another important consideration is that the code executing within the Task.Run is executing without a request context. So, ambient data like HttpContext.Current, current culture, thread principal, etc. are not going to be set correctly. You'll have to capture any important data before calling Task.Run and pass it down manually.
Trying to fix a problem in a classic ASP application, however I am inexperienced. Tried to find more info but was unable to.
The app instantiates a COM object for data retrieval which is not thread-safe, so the following instructions are added.
comObject=CreateObject("comServer.comObject")
returnValue=comObject.DoWork(.......)
...
comObject = Nothing
However, when processing two different http requests at the same time, the latter one seems to overwrite the first request, giving the first requester an error. It looks as if the comObject variable is shared between the requests.
How to instantiate the object in such a way that every separate request in IIS, gets it's own instance of the comObject?
Without knowing what the object does or how it does it, it's impossible to give specific advice. A general description will have to do:
The object is broken/buggy. It is the object's responsibility to handle the problem.
A COM object is supposed to handle all threading issues internally, or defer to COM STA apartments if it cannot do it, or doesn't want to (for those aspects that an STA can handle). This goes deep into the design of the object.
Regardless of COM Apartment choice, a DoWork(...) method with a semantic that precludes multiple separate COM objects in separate threads from handling simultaneous calls - is a seriously problematic design at best. A proper design would either include mechanisms to handle the conflict explicitly, or just hide the conflict from the calling code and handle the conflict internally.
Depending on the details of what DoWork() does, there might be ways to fix the object in such a way that the calls can succeed in parallel, or block each other so the calls are effectively serialized, or to cause the second call to throw a "You already called me" error. Again, which approach is more appropriate depends heavily on what the method does.
If you can't modify this broken component, your best option would be to write a COM wrapper that ensures serialization to the real object.
In any case, there is nothing reasonable you can do from the client (ASP VBScript) side.
I'm developing an app with VS2013, using EF6.02, and Web API 2. I'm using the ASP.NET SPA template, and creating a RESTful api against an entity framework data source backed by a sql server. (In development, this resides on the SQL Server local instance.)
I've got two API methods so far (one that just reads data, one that writes data), and I'm testing them by calling them in the javascript. When I only call a single method in my script, either one works perfectly. But if I call both in script (without waiting for either's callback to fire), I get bad results and different exceptions in the debugger. Some exceptions state that the save can't be completed because there are pending transactions. Another exception stated something about a conflict with other threads. And sometimes, the read operation fails with a null pointer exception when trying to read a result set.
"New transaction is not allowed because there are other threads running in the session."
This makes me question if I'm correctly getting a new DBContext per request. My code for this looks like:
static Startup()
{
context = new Data.SqlServer.AppDbContext();
...
}
and then whenever instantiating a unit of work, I access Startup.context.
I've tried to implement the unit of work pattern, and each request shares a single UOW object which has a single DBContext object.
My question: Do I have additional responsibility to ensure that web requests "play nicely" with eachother? I hope that this is a problem that others have already dealt with. Perhaps the errors that I'm seeing are legitimate in the sense that if one user's data is being touched, it is temporarily in an invalid state and if other requests come in at that exact moment, they indeed will fail (and I should code anticipating these failures). I guess that even if each request has its own DBContext, they still share the same underlying SQL data source so perhaps that's causing issues.
I can try to put together a testcase, but I get differing behavior depending on where I put breakpoints and how long I spend on them, reaffirming to me that this is timing related.
Thanks for any help or suggestions...
-Ben
Your problem is where you are setting your context. The Startup method is for when the entire application starts, thus any request made will all use the same context. This is not a per request setup, but rather a per application setup. As to why you are getting the errors, EntityFramework is NOT thread-safe. Since IIS spawns many threads to handle concurrent request, your single context is being used across multiple threads.
As for a solution, you can look into
-Dependency Injection frameworks (such as Ninject or Unity)
-place a using statement in your UnitOfWork classes
using(var context = new Data.SqlServer.AppDbContext()){//do stuff}
-Or, I have seen instances of people creating a class that gets the context for that request and stores it in the HttpContext.Cache[] element (using a unique name so you can retrieve it in another class easily), making it so that you will reuse the same context for the same request. Something like this:
public AppDbContext GetDbContext()
{
var httpContext = HttpContext.Current;
if (httpContext == null) return new AppDbContext();
const string contextTypeKey = "AppDbContext";
if (httpContext.Items[contextTypeKey] == null)
{
httpContext.Items.Add(contextTypeKey, new AppDbContext());
}
return httpContext.Items[contextTypeKey] as AppDbContext;
}
To use the above method, make a simple call var context = GetDbContext();
Note
We have all of the above methods, but this is specifically to the third method. It seems to work well with two caveats. First, do not use this in a using statement as it will not be available to any other classes during the scope of the request (you dispose it). And secondly, ensure that you have a call on Application_EndRequest that does actually dispose of it. We saw these little buggers hanging around after the request ended in memory causing a huge spike in memory usage.
I have a program in which it insert a raw in a table after certain operations. I wan to call a web service in code behind to do some special tasks by the using of info that there is in the inserted row.
How I can do that?
Is it good idea to invoke this web service from a stored procedure or not? What are the other options?
More Details: Actually, I have an operation in my web application that take a long time to be completed and it is seriously time consuming operation. I don't want client wait until this process finish. That is why I decide write a web service to do this process in the background.
Therefore, I think it may be a good idea that when client request receive I insert his request in a table and call a web service to handle it. Moreover, I do not want to wait until web service return the result, so I will aware client from its result through the report. I do not know what is the best solution to handle it.
I usually keep myself far away from table triggers(it sounds like you're about to use an on insert trigger for a table).
I don't know your specific situation but you could either :
Call the webservice before or after you call the stored procedure, this way the data layer(stored proc) only handles data and nothing more. You're logical layer will handle the logic of calling an extra webservice.
Write a service that will periodicly read a table and notify the webservice of the latest modifications. More messy but it resembles more the effect you're trying to achieve.
There are probably more solutions but i'd need more information on what it exactly is you're doing. Right now it's kinda vague :)
It is never a good idea to call webservice from Stored procs or other DB objects. You can call it from your code, just after you execute the insert and commit it.
The problem it sounds like is that you cannot guarantee that the web service will be called unless you call it before committing the transaction. However, it sounds like the web service needs to be called after commit. In this case, it sounds like you should use a message queue. You could either build one in your database or you could use one off the shelf (http://aws.amazon.com/sqs/ or http://www.windowsazure.com/en-us/home/features/messaging/).
The steps would be:
Insert message into queue (after this is success you can return the call, depending on what your contract with the caller is)
Read message
Insert into table
Call web service
Delete message
The downside is that you will need to make the operations (inserting into the table and calling the web service) idempotent.