.AsNoTracking() always on for certains DbSets for entity framework - entity-framework

Can I turn off tracking for a certain DbSet all the time without doing it on the context? I dont want to have to always remember to do it when pulling a query.
var locations = _venuesRepository.DataContext.Courts.AsNoTracking().ToList();

That is a feature of EF Core.
You can set the DbContext.ChangeTracker.QueryTrackingBehavior Property.
Logically, there also is an AsTracking() method in Core.
But when you are asking for the regular EF (6.x) then no, there is no such feature as far as I know.

Related

Filtering after i have done a ThenInclude in Entity Framework Core

i have a few tables such as:
User -> UserRole -> Role
I am using EF Core 2
I have a query like
_dbContext.User.Include(x=>x.UserRoles).ThenInclude(y=>y.Roles).Where(x.Active)
The role table also has an active(bool) column.
How can i filter the roles to only return where active is true.
Do i need to do some complex where condition traversing through all the tables as i don't have access to the roles variable in my where clause.
Also Is this something that will be easier in EF Core 3?
By default, EF Core doesn't support to filter in the Include method. It doesn't support it either in EF Core 3.x
Disclaimer: I'm the owner of the project Entity Framework Plus
The EF+ Query IncludeFilter (free and open source) allows easily filter included entities.
The ThenInclude is not yet supported but you just have to include the last filter to have the same behavior.
Example:
_dbContext.User
.IncludeFilter(x=>x.UserRoles)
.IncludeFilter(x=>x.UserRoles.SelectMany(y => y.Roles.Where(z => z.Active)))
Not a straight answer, mind you, but if this a "normal" requirement, that is, you always, or almost always, want to only return active roles, you may want to look at global filters, a feature that exists since EF Core 2.x. Global filters allow you to set restrictions per entity, such as "Active = true", "IsDeleted = false", etc. Global filters can be switched off, should you need to.
As to your answer, there is no obvious way to do that, other than looking at the Role entity, filtering it, and then projecting back to the root entity that you want, AFAIK.

Is it possible to tell if an entity is tracked?

I'm using Entity Framework 4.1. I've implemented a base repository using lots of the examples online. My repository get methods take a bool parameter to decide whether to track the entities. Sometimes, I want to load an entity and track it, other times, for some entities, I simply want to read them and display them (i.e. in a graph). In this situation there is never a need to edit, so I don't want the overhead of tracking them. Also, graph entities are sent to a silverlight client, so the entities are disconnected from the context. Hence my Get methods can return a list of entities that are either tracked or not. This is achieved dynamically creating the query as follows:
DbQuery<E> query = Context.Set<E>();
// Track the entities in the context?
if (!trackEntities)
{
query = query.AsNoTracking();
}
However, I now want to enable the user to interact with the graph and edit it. This will not happen very often, so I still want to get some entities without tracking them but to have the ability to save them. To do this I simply attach them to the context and set the state as modified. Everything is working so far.
I am auditing any changes by overriding the SaveChanges method. As explained above I may, in some low cases, need to save modified entities that were disconnected. So to audit, I have to retrieve the current values from the database and then compare to work out what was changed while disconnected. If the entity has been tracked, there is no need to get the old values, as I've got access to them via the state manager. I'm not using self tracking entities, as this is overkill for my requirements.
QUESTION: In my auditing method I simply want to know if the modified entity is tracked or not, i.e. do I need to go to the db and get the original values?
Cheers
DbContext.ChangeTracker.Entries (http://msdn.microsoft.com/en-us/library/gg679172(v=vs.103).aspx) returns DbEntityEntry objects for all tracked entities. DbEntityEntry has Entity property that you could use to find out whether the entity is tracked. Something like
var isTracked = ctx.ChangeTracker.Entries().Any(e => Object.ReferenceEquals(e.Entity, myEntity));

What is the overhead of Entity Framework tracking?

I've just been talking with a colleague about Entity Framework change tracking. We eventually figured out that my context interface should have
IDBSet<MyPoco> MyThings { get; }
rather than
IQueryable<MyPoco> MyThings { get; }
and that my POCO should also have all it's properties as virtual.
Using the debugger we could then see the tracking objects and also that the results contained proxies to my actual POCOs.
If I don't have my POCO properties as virtual and have my context interface using IQueryable<> instead of IDbSet<> I don't get any of that.
In this instance I am only querying the database, but in the future will want to update the database via Entity Framework.
So, to make my life easier in the future when I come to look at this code as a reference, is there any performance penalty in having the tracking info/proxies there when I will never make use of them?
There is a performance penalty of tacking entities in EF. When you query using entity framework EF will keep a copy of values loaded from database. Also single Context instance keeps track of only single instance of an entity. So EF has to check whether it already has a copy of the entity before it creates an instance(ie. There will be lot of comparisons going behind the scenes).
So avoid it if you don't need it. You can do so as follows.
IQueryable<MyPoco> MyThings { get { return db.MyThings.AsNoTracking(); } }
MSDN page on Stages of Query Execution details the cost associated with each step of query execution.
Edit:
You should not expose IDBSet<MyPoco> MyThings because that tells the consumer of your API that your entities can be added, updated and deleted when in fact you intend to query the data.
Navigation properties in the model classes as declared as virtual so as to imply lazy load feature which means the navigation property will only be needed if required. As far as the Entity objects are concerned, there main aim is to load the specific table records from the database into the DbSet which comes from DbContext. You can't use IQueryable in this case. Also, it doesn't make any sense with the DataContext. IQueryable is an altogether different interface

WCF, Entity Framework 4.1 and Entity's State

I am developing an application which will expose WCF services. I am using Entity Framework 4.1 at the DAL. The problem is when I load some entity (let say a Customer that has Order which in turn has OrderDetail). After loading it I make some changes in Customer, Order and OrderDetail objects (some new orders are added and some existing orders are removed/updated) and send the object graph to WCF service to update it as following.
Customer oCustomer;
using(var context = new MyContext) //MyContext is dbContext
{
oCustomer = context.Include("Order.OrderDetail").Find(1);
}
oCustomer.Name ="blah blah";
Order oOrder1 = oCustomer.Order.Where(obj=>obj.Id == 2);
oOrder1.Description = "blah blah";
oOrder1.OrderDetail.Quantity = 10;
Order oOrder2 = new Order { ... } //properties of Order are set.
oCustomer.Order.Add(oOrder2);
oCustomer.Order.Remove(context.Order.Find(1));
ServiceClient client = new ServiceClient();
client.SaveCustomer(oCustomer);
Now when I receive the updated ObjectGraph of Customer at Server side I don't know which Order was removed and which was modified, since there is no changetracking now. How can I determine that which Order to Delete and Which Order to Modify? Is there any way to track the changes in my object graph in Entity Framework 4.1?
NOTE: Previously I used Self Tracking Entities which solved this problem but I had to get rid of STEs since my WCF service is gonna be used by Java Client apps as well. So, STEs are not an option for me.
I wonder if it makes any sense to answer your questions because it looks like you don't read answers.
You asked question about STEs and you got answers about their usability.
I added link where it was explicitly described that they are not for interoperable scenarios
Richard posted very good links about STEs and about custom change tracking - btw. it is exactly what you are looking for now
You probably didn't read those answers because you used STEs and after that you asked a question how to use STEs in Java client.
What surprise me even more you did duplicate of your own question about STE and EFv4.1
Can I use Self Tracking Entities and DBContext in Entity Framework 4.1?
Using STE entities in Entity Framework 4.1
Today you already get an answer for this question in another your question.
So what answer do you expect? Does it worth it to answer your questions if you don't read answers?
Answer:
There isn't STE template for DbContext and once you are not using STEs you must handle change tracking completely yourselves because EF doesn't help you. The easiest approach is described in your previous question - load the object graph again in the service and merge incoming graph to attached entities so that context can track changes. The more complex solution is described in the link #Richard provided in one of your former questions about STE - you must add some state property to each transferred entity and client must set them correctly and post them back to you so that you can manually set correct state for each entity once you attach them - this can be little bit complex in case some relations.
As far as know there is no way to track changes of a detached object graph aside from Self Tracking Entities (which you can't use as you say).
What I usually do to update a detached graph is to reload the original graph from the database, compare the original with the changed graph (hand-written code case by case) to see which entities have been added, modified and deleted, write the changes into the original and save the context.
An example to this procedure (for one parent and a child collection, for instance Customer and Order collection) is in the answers to this question: The relationship could not be changed because one or more of the foreign-key properties is non-nullable
It's unfortunately getting quite complex if you have to deal with a deeper hierarchy of entities. As far as I can see EF doesn't offer any kind of automatic merging of a changed graph into the original, only for the very simple case where an entity only has scalar and complex properties which have been changed. As soon as navigation properties are involved you have no support from EF anymore and you have to write the update logic yourself.

Ado Entity Framework when should you use attach/detach

In ADO.net EF, when should you call the context.Attach() and the context.Detach() methods and how do these calls affect the data being returned or being inserted?
This is one of those questions where, "If you have to ask, you probably should not be doing it." The Entity Framework will implicitly attach entities in cases where it is obvious that this needs to happen. You really only ever need to explicitly attach and detach entities in cases where you are using more than one ObjectContext at once. Because this can be quite confusing, due to the implicit attachment which happens in the course of normal Entity Framework operations, I strongly recommend that people new to the Entity Framework use only one ObjectContext at a time. If you do this, you should never need to explicitly call Attach or Detach.
Calling, say, Attach does not really affect the data returned, insofar as it's scaler properties are concerned. But if it refers to other entities which are already loaded into the context into which it is attached, then these properties will be pre-populated without explicit loading. That said, entities returned from a query are already attached, so you cannot attach them.
Attaching Objects (Entity Framework)
http://msdn.microsoft.com/en-us/library/bb896271.aspx
Detaching Objects (Entity Framework)
http://msdn.microsoft.com/en-us/library/bb738611.aspx