Modifying Entity Framework Entities from Multiple Threads - c#

I have a UI thread which enables the user to set certain properties of an entity.
I also have worker threads which will automatically modify properties of an entity that, importantly, the user does not have access to.
Would it be safe to have different DbContexts per thread and just depend on my programming to always avoid modifying the same property and then attempting to SaveChanges() on a context which has the same entity modified in different ways?
Or is there a safer way of doing this, i.e. a way in which it will be possible for a programmer to some day change the code such that the same property is modified from two different contexts safely? Or is this latter situation simply one where the programmer has to be careful/refactor around?

Theoretical part
There are three ways to resolve the concurrency issues in the multi-threading environment:
pessimistic, this can easily be done with locks for an item being edited - no one else can edit the item already being edited. This is very hard to implement approach, and this way is quite bad from performance view - all the editing threads are waiting for a single writer, and just wasting the system resources.
optimistic, this is default way to resolve the issues. The main idea is that you continue the operation until you have a success. There are a lot of algorithm already introduced, I encourage you to read whole wiki-article and, may be, some additional references and/or books on theme.
semi-optimistic, this is a hybrid approach, this way is being used if you need to lock some operations, but not all.
Practice part
Entity framework authors encourage you to use the optimistic way in your app. The simple use-case is to add RowVersion or similar-named property to your model, and catch the DBUpdatedException during the UPDATE.
You can use the Code-First solution, like this:
[Timestamp]
public byte[] RowVersion { get; set; }
or Database-First solution (add column with database editor):
After that, your code for a simple case will be like:
using (var context = new SchoolDBEntities())
{
try
{
context.Entry(student1WithUser2).State = EntityState.Modified;
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("Optimistic Concurrency exception occured");
}
}
As I understood, you have to examine some properties of your data source, so I suggest you to read a great article regarding such use-cases (it is about an MVC-application, but I'm sure that you can manage out the main idea).
You can also find several articles regarding concurrency in Entity Framework on MSDN:
Optimistic Concurrency Patterns
Resolving optimistic concurrency exceptions with Reload (database wins)
Resolving optimistic concurrency exceptions as client wins
Custom resolution of optimistic concurrency exceptions
Custom resolution of optimistic concurrency exceptions using objects
Working with Property Values
Getting and setting the current or original value of an individual property
Getting and setting the current value of an unmapped property
Checking whether a property is marked as modified
Marking a property as modified
Reading current, original, and database values for all properties of an entity
Setting current or original values from another object
Setting current or original values from a dictionary
Setting current or original values from a dictionary using Property
Creating a cloned object containing current, original, or database values
Getting and setting the current or original values of complex properties
Using DbPropertyValues to access complex properties
As you can see, this situation relies completely on a developer side, and you have a great amount of patterns you may choose to resolve you concurrent issues by yourself.

Related

NHibernate - Eager load graphs of objects with multiple queries

I want to cache a never-changing aggregate which would be accessible by a root object only (all other entities are accessible only by using Reference/HasMany properties on the root object)?
Should I use NHibernate (which we are already using) second-level-cache or is it better to build some sort of singleton that provides access to all entities in the aggregate?
I found a blog post about getting everything with MultiQuery but my database does not support it.
The 'old way' to do this would be to
Do a select * from all aggregate tables
Loop the entities and set the References and the Collections manually
Something like:
foreach (var e in Entities)
{
e.Parent = loadedParentEntities.SingleOrDefault(pe => e.ParentId = pe.Id);
}
But surely there is a way to tell NHibernate to do this for me?
Update
Currently I tried merely fetching everything from the db and hope NHibernate does all the reference setting. It does not however :(
var getRoot = Session.Query<RootObject>().ToList();
var getRoot_hasMany = Session.Query<RootObjectCollection>().ToList();
var getRoot_hasMany_ref = Session.Query<RootObjectCollectionReference>().ToList();
var getRoot_hasMany_hasMany = Session.Query<RootObjectCollectionCollection>().ToList();
Domain:
Root objects are getRoot. These have a collection property 'HasMany'. These HasMany have each a reference back to GetRoot, and a reference to another entity (getRoot_hasMany_ref), and a collection of their own (getRoot_hasMany_hasMany). If this doesn't make sense, I'll create an ERD but the actual structure is not really relevant for the question (I think).
This results in 4 queries being executed. (which is good)
However, when accessing properties like getRoot.First().HasMany.First().Ref or getRoot.First().HasMany.First().HasMany().First() it still results in extra queries being executed even altough everything should already be known to the ISession?
So how do I tell NHibernate to perform those 4 queries and then build the graphs without using any proxy properties, ... so that I have access to everything even after the ISession went out of scope?
I think there are several questions in one.
I stopped trying to trick NHibernate too much. I wouldn't access entities from multiple threads, because they are usually not thread safe. At least when using lazy loading. Caching lazy entities is therefore something evil.
I would avoid too many queries by the use of batch size, which is far the cleanest and easiest solution and in most cases "good enough". It's fully transparent to the business logic, which makes it so cool.
I would:
Consider not caching the entity at all. Use NH first level cache (say: always load it using session.Get()). Make use of lazy loading when only a small part of the data is used in a single transaction.
Is there is a proven need to cache the data, consider to turn off lazy loading at all (by making the entities non-lazy and setting all the collections to non lazy. Load the entity once and cache it. Still consider thread safety when accessing the data while it is still loaded.
Should the entities be lazy, because some instances of the same type are not in the cache, consider using a DTO-like structure as cache. Copy all data in a similar class structure which are not entities. This may sound like a lot of additional work, but at the end it will avoid many strange problems and safe you much time.
Usually, query time is less important as flush time. This time is used by NH to find which entities changed in a session. To avoid this, make entities read only if you can.
if the whole object tree never changes (config settings?) then just load them efficiently with all references/collections initialised
using(var Session = Sessionfactory = OpenSession())
{
var root = Session.Query<RootObject>().FetchMany(x => x.Collection).ToFutureValue();
Session.Query<RootObjectCollection>().Fetch(x => x.Ref).FetchMany(x => x.Collection).ToFuture();
// Do something with root.Value
}

Check to see if Entity has been Deleted

We're implementing Entity Framework inside a winforms application using DbContext/Code First and have the following question regarding the proper way to check/handle when an entity has been deleted/updated in another context.
For example, we have some auxiliary table data (e.g. StateCodes) and the user could go in another and add/remove states as needed. This auxiliary editor form utilizes it's own DbContext and saves the changes once the user exits the form. Upon returning to the main form, the main context is unaware of the changes made to the database so we'd like to reload the DbSet for the entity. Unfortunately, it appears that if we remove the "MI" state code it still exists in the Local property of the DbSet with an EntityState of unchanged even after we call "Load" to bring in everything.
Outside of completely disposing of the main context would the following be the best way to check and see if what entities have been removed from the database?
foreach (State state in db.States.Local)
{
DbEntityEntry entry = db.Entry(state);
DbPropertyValues databaseValues = entry.GetDatabaseValues();
if (databaseValues == null)
{
db.States.Remove(state);
}
else
{
entry.OriginalValues.SetValues(databaseValues);
}
}
Thank you for your help
You shouldn't keep the context live past its unit of work. The context should only survive as long as its needed, otherwise you're bound to run in to caching pitfalls like you're observing. (Also, the context really isn't that heavy where instantiating it when you need it is overly time-consuming/resource intensive).
If you really must keep it alive, you may want to look in to passing the context to the auxiliary form.
Mirrored from my comment, figured it's best served as an answer
First, what Brad said. Only keep the context alive for the specific unit of work and dispose it. Not doing this will lead to nothing but headaches.
You can also check the entity's state by using the ObjectStateManager and pass in the object or entity key. You can also use the
public void Refresh(
RefreshMode refreshMode,
IEnumerable collection
)
method off of the Context. Also, you can check the entry state.
http://msdn.microsoft.com/en-us/library/bb503718.aspx

Inheritance situation not resolved properly in Entity Framework Code First

I have a Candidate class. When somebody deletes a Candidate, I want a DeletedCandidate which is derived from Candidate to be stored in a separate table.
How can I model this in EF, Code first? I think my best option is TBC, but when I use the following in Context, a System.Data.MappingException is thrown.
modelBuilder.Entity<DeletedCandidate>().Map(d => {
d.ToTable("DeletedCandidate");
d.MapInheritedProperties();
});
I would not use inheritance for archiving-like tasks. You will always have to make a distinction between Candidates and DeletedCandidates in your mainstream application code. With EF you'll have to do that by always retrieving candidates by OfType<Candidate>.
I would make a separate class (and table) for DeletedCandidates. Thus, you can always get to them when needed, but they never get in harm's way in the rest of your code. A drawback may be that you always have to keep the properties (and columns) of the two in sync. This could be relieved by having both classes implement a common interface (which you can easily do with code-first).
If you need to preserve foreign key relationships to DeletedCandidates it's a different story. In that case I think the best you can do is using a deleted flag (but you're going to need filtering to get the active candidates).
Just an advice :D.

Domain Model with Nhibernate design issue

I´m trying to get started in the “DDD with C#” world.
I use NHibernate as my ORM tool, thus trying to develop a PI(Persistence Ignorance) model.
However, in some of my entities (which are being represented as POCOS) I have business rules in the setters of my properties.
For example, I have a “User” entity which have a flag that indicates if this user is blocked or not, when this flag is true a second field called “Block Date”
must be automatically filled whith the current date.
Everything seems very clear and simple, but the problem arises in the moment that I´m recovering users that has already persisted in the database, even though
the blocked users will have their “Blocked Dates” update to the current date, according whit this logic.
Initially I thought in a second flag “isLoaded” that would indicates that the object is being hydrated by NHibernate and then this logic wouldn´t be launched,
however this didn´t seem like PI. Any suggestion on how to improve this?
You can define field access strategy in your mapping for the IsBlocked property. Basically, you would say to NHibernate to use underlying private field (_isBlocked) instead of property and hence, your setter logic in IsBlocked property won't be executed.
This SO question has a good answer on access strategies.
Official NHibernate documentation.
If you are using Fluent NHibernate for mapping, this is how you could define it:
Map(x => x.IsBlocked).Access.CamelCaseField(Prefix.Underscore);
In addition to Miroslavs solution for the NHibernate problem, I'd really recommend moving away from putting logic behind property setters, especially when other fields need to be changed.
public void Block()
{
_isBlocked = true;
_blockedDate = DateTime.Now;
}
See answers to this question for why.

Does LINQ to Entities reuse instances of objects?

Using LINQ to Entities sounds like a great way to query against a database and get actual CLR objects that I can modify, data bind against and so forth. But if I perform the same query a second time do I get back references to the same CLR objects or an entirely new set?
I do not want multiple queries to generate an ever growing number of copies of the same actual data. The problem here is that I could alter the contents of one entity and save it back to the database but another instance of the entity is still in existence elsewhere and holding the old data.
Within the same DataContext, my understanding is that you'll always get the same objects - for queries which return full objects instead of projections.
Different DataContexts will fetch different objects, however - so there's a risk of seeing stale data there, yes.
In the same DataContext you would get the same object if it's queried (DataContext maintains internal cache for this).
Be aware that that the objects you deal are most likely mutable, so instead of one problem (data duplication) you can get another (concurrent access).
Depending on business case it may be ok to let the second transaction with stale data to fail on commit.
Also, imagine a good old IDataReader/DataSet scenario. Two queries would return two different readers that would fill different datasets. So the data duplication problem isn't ORM specific.
[oops; note that this reply applies to Linq-to-SQL, not Entity Framework.]
I've left it here (rather than delete) because it is partly on-topic, and might be useful.
Further to the other replies, note that the data-context also has the ability to avoid doing a round-trip for simply "by primary key" queries - it will check the cache first.
Unfortunately, it was completely broken in 3.5, and is still half-broken in 3.5SP1, but it works for some queries. This can save a lot of time if you are getting individual objects.
So basically, IIRC you need to use:
// uses object identity cache (IIRC)
var obj = ctx.Single(x=>x.Id == id);
But not:
// causes round-trip (IIRC)
var obj = ctx.Where(x=>x.Id == id).Single();

Categories

Resources