How to invoke a delegate beginInvoke within a DBContext - entity-framework

I have a code like this
using (SomeDBContext db = new SomeDBContext())
{
foreach (var r in someColection)
{
MyDelegate.BeginInvoke(db, parm1, parm2, etc, null, null);
}
}
The problem is, the function that is fed to MyDelegate uses the db dbcontext passed to it, and since the delegate is run asynchronously the db context was closed while the function is trying to access the database. Could someone please help resolving this problem? Thank you sooo much!

A Context is not thread safe,you will have problems if you try to use it
(Unfortunately sometimes you will not notice anything wrong... )
Anyway ,the best approach is to create a new Context inside your method which will solve your original problem

Related

Entity Framework Core: SaveChanges() NON-async throws "A second operation was started on this context before a previous operation completed."

I am fairly new to Entity Framework and everything has been moving smoothly, until I encountered this error. My code is attempting to save children of a parent table using SaveChanges() but I get this error:
A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext.
This message seems tied to async calls and having to use await - SaveChangesAsync(). However I am NOT calling the async version of the SaveChanges() method but still get a thread error message.
My code is fairly simple:
public void CreateRange(IList<Section> sections)
{
// Add new sections and save context.
_SqlRunnerContext.sectionsDbSet.AddRange(sections);
_SqlRunnerContext.SaveChanges(); // This line throws the error.
}
The error seems to occur when there are at least two entries in the list. Which makes me think it's the way that Entity Framework is handling the save internally.
The code that calls this method creates a new repository which in turn creates a new dao and SqlContext. Given this I wouldn't think it would be something outside of this code causing the issue. I have also tried a foreach loop and save each item individually with the same error.
If anyone could give me a suggestion or idea what to try, it would be much appreciated.
Thanks again,
Adam
Instead of deleting all records then re-inserting. I change the code to simply update if it exists and add if new. This has resolved the issue.

calling the Execute method of IExternalLateBoundService

The question about the calling of the custom .net method implemented in the TurnKey_ExternalLateBound.dll.
I remember that it worked for me, but it was long time ago.
I tried this article and I put simple code:
public IElement Execute(IClassifier classifier, IObject theobject, IMethod method, IModifiableVariableList variableList)
{
throw new NotImplementedException();
}
But I got nothing in the Turnkey. The tagged value of the class's method is ok. Viewmodel's action column calls this method.
Could you please advise what should I do else?
Thanks a lot!

Using a dynamic connection string with the Breeze EFContextProvider

At the moment i have an application (web/silverlight) where the connectionstring for my ObjectContext is dynamic. It is based on how a user logs in because each of my customers have their own database. ie.. username#domain. I'm trying to find a way to use the EFContextProvider which would be by either passing the ObjectContext through the constructor, or by overriding the GetConnectionString, which sadly both aren't supported.
Is there a way to accomplish this, or can i download the source for the EFContextProvider somewhere so i can implement it myself ?
Thanks in advance.
This question was posted by Marcel on our IdeaBlade forums. I am reposting the question and answer here since I think it will be useful to the Breeze Stack Overflow community.
You shouldn't have to download the source and modify it for such a simple thing. And now you won't have to.
We've pushed to GitHub a simple update to EFContextProvider. This change will appear in the next Breeze Runtime version (> 0.81.2).
Where EFContextProvider used to create the 'T' (your ObjectContext/DbContext) as follows:
_context = new T();
It now calls upon a virtual method, T CreateContext() instead, whose default implementation is:
protected virtual T CreateContext() {
return new T();
}
Override and replace that in your EFContextProvider subclass and you will be able to make your context of type 'T' just the way you like it.
N.B.: The base EFContextProvider will still do a little post-creation configuration to make sure it behaves as we expect; we don't want the context doing any lazy loading or creating proxies.
So if 'T' is an ObjectContext, the provider will do this:
objCtx.ContextOptions.LazyLoadingEnabled = false;
and if 'T' is a DbContext it will do this:
dbCtx.Configuration.ProxyCreationEnabled = false;
dbCtx.Configuration.LazyLoadingEnabled = false;
I downloaded the source and added a constructor to the
EFContextProvider which accepts an instance of T to be able to use an
existing ObjectContext/DbContext which works like a charm.
Marcel figured it out by himself and answered his own question on our forum.
The CreateContext virtual method, mentioned by Ward, is now available in v 0.83.2

Force Entity Framework to return a new instance

We have a scenario in our code when only a few properties of an entity are allowed to be changed. To guarantee that, we have code similar to this:
public void SaveCustomer(Customer customer)
{
var originalCustomer = dbContext.GetCustomerById(customer.Id);
if (customer.Name != originalCustomer.Name)
{
throw new Exception("Customer name may not be changed.");
}
originalCustomer.Address = customer.Address;
originalCustomer.City = customer.City;
dbContext.SaveChanges();
}
The problem with this code is that the call to dbContext.GetCustomerById does not always gives me a new instance of the Customer class. If the customer already has been fetched from the database, Entity Framework will keep the instance in memory and return it on every subsequent call.
This leads us to the actual problem - customer and originalCustomer may refer to the same instance. In that case, customer.Name will be equal to originalCustomer.Name and we will not be able to detect if it differs from the database.
I guess the same problem exists with most other ORMs as well, because of the identitymap design pattern.
Any ideas how this can be solved? Can I somehow force EF to always give me a new instance of the customer class?
Or should we refactor the code instead? Does anyone know of any good design patterns for this scenario?
you can try by detaching the entity from the context, this will remove all the references to the context (as well as the identitymap behaviour).
So, before passing the Customer to your method you can detach it:
yourContext.Detach(customer);

Entity Framework 4 ObjectContext Lifetime

Ive just started using EF4 with the repository pattern. Im having to call the dispose method after every use of context or wrap code arround in the using block. Can I use the ObjectContext without doing this in every method I write or is there a better way of handling this in the repository.
Also I dont want to pass the ObjectContext to the repository from the UI as well.
To do this as resource effectively as possible without dependency injection, I would suggest that you implement a private, lazy-loading property for the object context.
private ObjectContext _context;
private ObjectContext Context
{ get
{
return _context ?? (_context = new ObjectContext());
}
}
Next, make your repository implement IDisposable and take care of the object context in your dispose method:
public Repository : IDisposable
{
...
public void Dispose()
{
_context.Dispose();
}
}
Then, you just use the property in all your methods, and wrap usage of your repository in using statements.
To decrease traffic to the database, you could also factor out the saving to a separate method on the repository, which just forwards the call to the object context. That way you get more control of when data is saved in the UI layer, even though you don't control how. That means you could do
using (var repo = new Repository())
{
repo.AddSomeStuff("this", "is", true);
repo.ChangeSomethingElse("yes, please");
repo.Save();
}
and there would only be one call from EF to the database. On the other hand, if you do
using (var repo = new Repository())
{
repo.AddSomeStuff("this", "is", true);
repo.ChangeSomethingElse("yes, please");
}
nothing happens, which might be confusing.
The general pattern for using an object context is:
public BusinessObject GetSomething(){
using (MyObjectContext context = new MyObjectContext()){
//..do fun stuff
}
}
Which hopefully is the pattern you are using. Calling dispose seems a little overkill when you can just use a "using" statement.
Another option is if you are going to be doing multiple DB queries in a flow. I have seen a pattern where you can reuse the same context within the thread. People basically implement a Thread based singleton pattern and pass around the context. Advantages to this is not having to rebuild the context, as well as some in memory caching. Downside is you could run into concurrency issues. Someone updating something that you have cached internally in EF.
I am guessing the second case doesn't really apply because it sounds like you are writting a small app. (that statement was based on your comments about passing a context from UI...a statement which will scare any good code architect).
If you are interested in a thread based singleton. First learn about the Singleton pattern, and then check out this blog about "DataContext" threads. You will have to change the "DataContext" type to the ObjectContext class but it would work.
EDIT
I will say I overlooked an obvious solution and that would be the below ;). Just using a property based Object Context and playing your repository in a using statement. It would be the same as the using example above, but you would implement IDisoposable.