Ran into a weird problem with RavenDB
public ActionResult Save(RandomModel model)
{
//Do some stuff, validate model etc..
RavenSession.Store(model);
RavenSession.SaveChanges();
var newListOfModels = RavenSession.Query<RandomModel>().ToList();
return View("randomview",newListOfModels);
}
The newListOfModels does not contain the model i just added with the store method.
However, if i add a Thread.Sleep(100) after savechanges the stored model is included in the new list.
Am i storing and Saving stuff to RavenDB the wrong way?
How should i be doing this?
Of course there is a work around by just adding the incoming model to the newListOfModels and running SaveChanges after for example in a basecontrollers onactionexecuted method.
My primary concern is why i need to delay the thread before i can query the documentsession and find my newly added model there.
RavenDB indexes are stale by their nature. From the documentation:
RavenDB performs data indexing in a background thread, which is
executed whenever new data comes in or existing data is updated.
Running this as a background thread allows the server to respond
quickly even when large amounts of data have changed, however in that
case you may query stale indexes.
So you need to tell RavenDB when querying to wait for the index to be refressed.
You can do with the various WaitFor... customization, you will most probably want the WaitForNonStaleResultsAsOfLastWrite option:
var newListOfModels = RavenSession
.Query<RandomModel>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()).ToList();
Related
having some strange issue happening with my code.
Let's say i have list of bananas i'm deleting in my database and send stored procedure request to also delete it in another DB from another service (that's why i have saveChanges and Refresh stuff in my code: to avoid OptimisticConcurrencyErrors that hapenned sometimes). We have syncronization tasks that get changes from another service and syncs values in our db:
foreach(var banana in bananaList)
{
//...
//some conditions
banana.SendDeleteRequestToService(); //after request sync process is triggered to update values in my db
banana.Delete(); //logical delete that place IsDeleted=1 in database
Connect.Refresh(banana); // method to refresh context in RefreshMode.Wins to avoid concurrency error
Connect.SaveChanges(true); //force to update deleted bananas
}
after what i'm getting bananaTrees that are linked with bananas in db and change banana tree status to "No bananas":
var bananaTreeList = bananaTree.GetList().Where(b => b.IsDeleted ==1);
bananaTreeList.ForEach(bt => bt.Status = "No bananas");
Connect.SaveChanges(true);
Issue is that some items from bananaTreeList are not getting status updated, though all bananas are being deleted and i see all bananaTrees in the list that need to have status changed when debugging. foreach also goes through all items i need, but status changes are not applied for some of the items.
I guess the main reason is due syncronization task (cannot stop or pause it) which is affecting database context and EF can't resolve changes from different sources. I want to understand how to update EF context so all of my bananaTrees would have their statuses updated correctly.
How to handle this kind of concurrency issues in EF? There is a lot of code in my project, but i tried to give the most important parts in my example.
The documentation for AsNoTracking() in Entity Framework Core says that any edits to it won't be persisted when the database context is saved.
I have noticed another difference when AsNoTracking() is used, namely that if the database context has unsaved edits and you query it with AsNoTracking(), those changes won't be returned.
The documentation makes it sound like only edits done TO an AsNoTracking() query won't be tracked and persisted on save, but it seems that the contents returned will also be different.
If this is indeed the intended behaviour, I am unsure of the best design pattern.
I have used AsNoTracking() on all my read-only queries, but this means I have a bug as my design is something like this:
Controller endpoint that modifies data:
Call something in a service that may or may not alter the db
Call something else in the service, that does a read-only query with AsNoTracking()
Controller saves the database context
The intention is that any controller endpoint can call any number of service methods that may or may not alter the database, the database contexts are scoped so they are shared between the calls, and ultimately the controller persists the changes.
The problem is that #2 in the above won't return changes done in #1. How should this be resolved? The services can call out to other services which may fetch some data from places that have already been modified, so I can't just pass the models around everywhere.
Should I just remove AsNoTracking() from everywhere and call it a day? Or should I add a save call after every write? Or is there something else I could do?
TLDR: I want AsNoTracking() to be used in read-only queries for speed, but it won't return any unsaved changes. Should I remove AsNoTracking(), save after every edit, or is there a better way?
Edit:
Here is a snippet of what I mean; any query with AsNoTracking() ignores any edits done to a context before it's been saved, making me wonder how AsNoTracking() could be useful at all then:
var userSessionEntry = await this.mainContext.Sessions
.Where(t => t.AccountId == session.AccountId).FirstAsync();
userSessionEntry.AccountId = Guid.Empty;
var userSessionEntry2 = await this.mainContext.Sessions
.Where(t => t.AccountId == session.AccountId).AsNoTracking().FirstAsync();
Console.WriteLine(userSessionEntry2.AccountId); // prints original AccountId and not an empty id
Edit 2:
I'm using the latest preview version of Entity Framework Core; 5.0.0-preview.5.20278.
Thanks.
The way AsNoTracking works is that it will always bypass the DbContext's own cache (change-tracked) entities, and directly execute a query on the database. This is what is meant by the definition. The cached data can be different than the underlying database data, assuming someone else makes changes to the same entities your working with.
However, per your design, if all services in your controller use the same exact DbContext instance, then you will be fine. There are ways to do this by using scoped dependency injection of your database context to any services you have. This way all parts of your service request should use the same instance.
If you need the most up-to-date data all the time, then you'll need to use AsNoTracking for all queries you make so you always hit the database for the freshest data.
You can still make edits to entities that are no-longer change tracked, but some additional code will be required:
var managers = await DbContext.Set<Employee>()
.AsNoTracking()
.Where(x => x.IsManager)
.ToListAsync();
foreach (var manager in managers)
{
manager.Salary += 10000;
var dbEntry = DbContext.DbEntry(manager);
dbEntry.Property(x => x.Salary).IsModified = true;
}
await DbContext.SaveChangesAsync();
You can use the above strategy to always ensure your working with the freshest data. If you have 1000's of users actively using your service, this can actually hit your database quite a lot, so some caching strategy would be in order.
I've got an Application which consists of 2 parts at the moment
A Viewer that receives data from a database using EF
A Service that manipulates data from the database at runtime.
The logic behind the scenes includes some projects such as repositories - data access is realized with a unit of work. The Viewer itself is a WPF-Form with an underlying ViewModel.
The ViewModel contains an ObservableCollection which is the datasource of my Viewer.
Now the question is - How am I able to retrieve the database-data every few minutes? I'm aware of the following two problems:
It's not the latest data my Repository is "loading" - does EF "smart" stuff and retrieves data from the local cache? If so, how can I force EF to load the data from the database?
Re-Setting the whole ObservableCollection or adding / removing entities from another thread / backgroundworker (with invokation) is not possible. How am I supposed to solve this?
I will add some of my code if needed but at the moment I don't think that this would help at all.
Edit:
public IEnumerable<Request> GetAllUnResolvedRequests() {
return AccessContext.Requests.Where(o => !o.IsResolved);
}
This piece of code won't get the latest data - I edit some rows manually (set IsResolved to true) but this method retrieves it nevertheless.
Edit2:
Edit3:
var requests = AccessContext.Requests.Where(o => o.Date >= fromDate && o.Date <= toDate).ToList();
foreach (var request in requests) {
AccessContext.Entry(request).Reload();
}
return requests;
Final Question:
The code above "solves" the problem - but in my opinion it's not clean. Is there another way?
When you access an entity on a database, the entity is cached (and tracked to track changes that your application does until you specify AsNoTracking).
This has some issues (for example, performance issues because the cache increases or you see an old version of entities that is your case).
For this reasons, when using EF you should work with Unit of work pattern (i.e. you should create a new context for every unit of work).
You can have a look to this Microsoft article to understand how implement Unit of work pattern.
http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
In your case using Reload is not a good choice because the application is not scalable. For every reload you are doing a query to database. If you just need to return desired entities the best way is to create a new context.
public IEnumerable<Request> GetAllUnResolvedRequests()
{
return GetNewContext().Requests.Where(o => !o.IsResolved).ToList();
}
Here is what you can do.
You can define the Task (which keeps running on ThreadPool) that periodically checks the Database (consider that periodically making EF to reload data has its own cost).
And You can define SQL Dependency on your query so that when there is a change in data, you can notify the main thread for the same.
What is the best way to refresh data in Entity Framework 5? I've got an WPF application showing statistics from a database where data is changing all the time. Every 10 seconds the application is updating the result but the default behaviour for EF seems to be to cache the previous results. I would thus like a way to invalidate the previous results so a new set of data can be loaded.
The context of interest is defined in the following way:
public partial class MyEntities: DbContext
{
...
public DbSet<Stat> Stats { get; set; }
...
}
After some reading I was able to find a few approaches, but I have no idea of how efficient these ways are and if they come with downsides.
Create a new instance of the entities object
using (var db = new MyEntities())
{
var stats = from s in db.Stats ...
}
This works but feels inefficient because there are many other places where data is retrieved, and I don't want to reopen a new connection every time I need some data. Wouldn't it be more efficient to keep the connection open and do it another way?
Call refresh on the ObjectContext
var stats = from s in db.Stats ...
ObjectContext.Refresh(RefreshMode.StoreWins, stats );
This also assumes I'm extracting ObjectContext from the dbContext in this way:
private MyEntities db = null;
private ObjectContext ObjectContext
{
get
{
return ((IObjectContextAdapter)db).ObjectContext;
}
}
This is the solution I'm using as it is now. It seems simple. But I read somewhere that ObjectContext nowadays isn't directly accessible in DbContext because the EF team doesn't think that anyone would need it, and that you can do all things you need directly in DbContext. This makes me think that maybe this is not the best way to do it, or?
I know there is a reload method of dbContext.Entry but since I'm not reloading a single entity but rather retrieve a list of entities, I don't really know if this way will work. If I get 5 stat objects in the first query, save them in a list and do a reload on them when it's time to update, I might miss out others that have been added to the list on the database. Or have I completely misunderstood the reload method? Can I do a reload on a DbSetspecified in MyEntities?
There are a number of questions above but what I mainly want to know is what is the best practice in EF5 for asking the same query to the database over and over again? It might very well be something that I haven't discovered yet...
Actually, and even if it seems counter intuitive, the first option is the correct one, see this
DbContext are design to have short lifespans, hence their instantiation cost is quite low compared to the cost of reloading everything, it's mostly due to things like caching, and their data loading designs in general.
That's also why EF works so "naturally" well with ASP .NET MVC, since the DbContext is instantiated at each request.
That doesn't mean you have to create DbContext all over the place of course, in your context, using a DbContext per update operation (the one happening every 10secs) seems good enough, if during that operation you would need to delete a particular row, for example, you would pass the DbContext around, not create a new one.
In the system I'm currently building I have to make webrequests to an API which provides a calculation service. This service requires a set of complex parameters which I have to retrieve from my database. Currently I'm using entity framework for retrieving these entities and for each entity I'm making a request to this api, retrieve the result and at the end save all results to the database (everything done synchronously)
There will be scaling issues with this approach when the set of entities increases (since I have to call the calculation service every 30 minutes on each entity). Because of this I would like to make the database retrieval and web request for an entity in parallell (or async) with the same operations for other entities. (Not with the purpose of reducing time for data loading but to do work while waiting for the webrequest to complete)
Since EF 5 context is not thread safe, what is my best alternatives for achieving this? Should I write specific SQL queries, use LINQ etc? Does anyone have code examples for a similar approach (db retrieval for webrequest in parallell)
EDIT
Adding a small code sample (very simplified). Assuming that the call to the webservice may take a couple of seconds this will not scale.
foreach(entityId in entityIds)
{
var entity = _repository.Find(entityId);
_repository.LoadData(entity);
_validator.ValidateData(entity);
var result = _webservice.Call(entity);
entity.State = result.State;
}
_repository.SaveChanges();
What you could do is to use a producer-consumer architecture: One thread accesses the database and adds the data to something like BlockingCollection. Another thread (or multiple threads) reads the data from the collection and performs the web request.
There are different ways for you to parallelize this. It all depends on what you really want/need.
One way would be to use a Paralle.ForEach.
Parallel.ForEach(
entityIds,
entityId =>
{
var entity = _repository.Find(entityId);
_repository.LoadData(entity);
_validator.ValidateData(entity);
var result = _webservice.Call(entity);
entity.State = result.State;
});
_repository.SaveChanges();