Entity Framework - persisting changes to database only partially - entity-framework-4

Is is possible to select what portion of the Entity Framework entities are persisted back to database?
ObjectContext.SaveChanges() saves everything but if I want to persist only certain items, how to do that?

You need to detach the objects you don't want persisted from the ObjectContext. You do this by assigning their EntityState to Detached as follows:
context.Products.First().State = EntityState.Detached
or
context.Detach(Products.First());

Use multiple contexts to keep track of different sets of data:
The following psuedo code should help you. Cleary there are more ways than just one to do this.
using(ObjectContext context1 = new ObjectContext())
{
using(ObjectContext context2 = new ObjectContext())
{
//Do Stuff
//Now only a portion of your changes are saved to the database
context2.SaveChanges();
}
}

Related

CoreData - creating new entity - Why don't you need to save this?

I figured you can create new entities (in swift 3) like this:
let person = Person(context: persistentContainer.viewContext)
person.name = "Some Name"
This seems to be it. It saves the new person permanently (I think so, at least).
Why don't you need to call saveContext()of AppDelegate. swift (or persistentContainer.viewContext.save() which is basically the same, right?)?
Every time you change some entity, you need to save it. Why isn't this the case when creating new entities?
Thanks in Advance !!!
According to your comments on your question, you ARE calling saveContext().
Go into your AppDelegate and check out applicationWillTerminate, saveContext() is called there.
In short, if you want to persist the data then yes, you need to call saveContext()
for your anser you have to understand the Core Data stack
https://developer.apple.com/library/ios/documentation/DataManagement/Devpedia-CoreData/coreDataStack.html#//apple_ref/doc/uid/TP40010398-CH25-SW1
Changes that you make to your managed objects are not committed to the parent store until you save the context.

DBContext (entity framework) and pre-loaded entities

I use code first in a web application where I have a form to upload text files and import the data into my database.
Each file may have up to 20.000+ records for import.
To speed things up I preload some entities so not to ask the DbContext every time. Then when I create an object for insert, I do for example:
myNewObject.Category = preloadedCategories.First(p => p.Code == code);
I have read some articles on the web because EF is extremey slow on batch inserts, so what I do is:
first use Configuration.AutoDetectChangesEnabled = false;
then every 1000 records I dispose the object and make a new one.
BUT! since the preloaded entities where loaded from a db context that was disposed, after making a new DbContext, I have a problem with preloadedCategories.First(p => p.Code == code). When I make a SaveChanges(), EF tries to also save the preloadedCategories.First(p => p.Code == code) object and fails.
So how can I achive this? I don't want to aks the DbContext every time to load some (non changing) objects. Is it possible?
thanks
When dealing with a large number of records in EF, a few things will help
As #janhartmann states, use .AsNoTracking()
As you stated, use Configuration.AutoDetectChangesEnabled = false, which will require the next point
Use context.Categories.Entry(category).State = EntityState.Modified to attach a disconnected entity to a context and mark is as modified
Also make check that preloadedCategories is no longer an IQuerable and that the data really is local and not trying to lazy load from the database.
If there are no changes to your Category object and you just want to link your myNewObject to an existing category, you have two options
Set the foreign key on myNewObject instead of the navigation property
Use context.Products.Entry(myNewObject).State = EntitySate.Added instead of context.Products.Add(myNewObject) to avoid it adding the entire graph of navigation properties
Good luck

Unable to clear cache in EF

Iam facing a problem while using factory model in MVC.
As i update and try to display the data from the same table, the update is being performed in the database but the updated data is not being fetched from the database.
I feel that it is fetching the data from the Entities and displaying the data.
I used Modelstate.clear() outputcache etc., but none of it worked.
code used:
For Update:
public virtual void Update(TObject TObject)
{
var entry = Context.Entry(TObject);
DbSet.Attach(TObject);
entry.State = EntityState.Modified;
}
calling Update method in my service and saving changes:
Registry.RepositoryFactory.GetUsersRepository().Update(userobj);
Registry.Context.SaveChanges();
Fetching data after save:
Select:
public virtual IQueryable<TObject> All()
{
return DbSet.AsQueryable();
}
I am able to update in the database, but as it try to retrieve the data immediately from the same table it is not hitting the database, i think it is fetching the data from the cache.
Any pointers are welcome.
Thanks in advance,
Girish.
I have followed the link provided by Damon, the problem is that Refresh occurs. But it is taking few seconds(2 or 3). The page has to load immediately.
The solution that has worked for me is that, while fetching the data from the repository, i am setting the entity using Set. And then i used Refresh method before fetching the data.
Code used:
DbSet set = ((DbContext)Context).Set();
((IObjectContextAdapter)Context).ObjectContext.Refresh(System.Data.Objects.RefreshMode.StoreWins, set);
return DbSet as IQueryable;
I'm going to guess that you are re-using the same EF Context object for both the Update and the Select. If the Context is not disposed of between these events you will end up with a stale context and data will be returned from the EF cache.
Make sure you are disposing of the EF context between calls with the best practise being to surround it in a Using statement. An alternative to this is to call Refresh() on the Context (See this question). You'll still need to dispose of the context at some point because otherwise it will continue to grow and your application will get slower and slower.
I've answered a similar question here.

Best way to have a single Entity using Magicalrecord

I'm looking for the best solution to implement this behavior:
I have an Entity called Customer and this will have only a single entry on Core Data, because the Customer will be only ONE.
What's the best solution to implement this? Is everytime check if the Entity exists before creating?
Many thanks
As mentioned, you can use for single object [NSUserDefaults standardUserDefaults].
But if you prefer use CoreData, write this:
Customer* customer = [Customer MR_findFirst];
if (customer != nil)
{
//do something with it
} else
{
[Customer MR_importFromObject:JSONToImport];
}
BDW:
MR_importFromObject method automatically check if exists entity with specific id (for id key it use attribute of your entity name plus "ID". (in your case "customerID") or key that named "mappedKeyName".
And if entity with this key already exist - Magical Record just update this entity.
So, if you specify this value it in your entity, just write:
[Customer MR_importFromObject:JSONToImport];
If there's only a single instance, the best solution is usually to not put it in Core Data. It gives you very little, and adds complexities like the one you're seeing. Save the necessary information in a property list, or even in user defaults.
Checking the entity exists before creating a new one is a good idea.
You can fetch all entities of your customer entity type and delete them all before adding a new one is another method.
You could also have a simple method that gets the current customer or creates one and then update all it's properties.
It sort of depends on how you get the data and what you want to happen with the related objects.

Changes not reflected in Database while using entity framework

I am accessing my database through ADO.NET Entity framework in MVC 3 Application.
I am updating my database through Stored Procedure.
But the changes are not reflected at run time.I mean to say i am able to see the changes only after restarting it.
What is the reason for the problem and How can i avoid it ?
I am using Repository pattern So at repository My code look like this
Ther Is One Function Which Save Changes
public void SaveNewAnswer(AnswerViewModel answer,string user)
{
SurveyAdminDBEntities _entities = new SurveyAdminDBEntities();
_entities.usp_SaveNewAnswer(answer.QuestionId, answer.AnswerName, answer.AnswerText, answer.AnswerOrder, answer.Status, user);
_entities.SaveChanges();
}
Data Retreival Code
public IEnumerableGetMultipleChoiceQuestions(string questionId)
{
SurveyAdminDBEntities _entities = new SurveyAdminDBEntities();
_entities.AcceptAllChanges();
_entities.SaveChanges();
return _entities.usp_GetMultipleChoiceQuestions(Int32.Parse(questionId));
}
But Changes are not reflected till the time i don't clode the session of the browser and run it again .
Please help !
Thank You In advance
Are you calling context.SaveChanges() on your Entities (DbContext/ObjectContext) object? Are you using a transaction that you haven't committed?
If you have an uncommitted transaction in your sproc, you can try creating your own entity transaction and seeing if committing your transaction will commit the nested transaction as well. The problem is that calling SaveChanges() automatically begins and commits a transaction, so this may not be any different than that.
I would also call _entities.AcceptAllChanges() in your save operation.
public void SaveNewAnswer(AnswerViewModel answer,string user)
{
SurveyAdminDBEntities _entities = new SurveyAdminDBEntities();
_entities.Connection.Open();
System.Data.Common.DbTransaction tran = _entities.Connection.BeginTransaction();
try
{
_entities.usp_SaveNewAnswer(answer.QuestionId, answer.AnswerName, answer.AnswerText, answer.AnswerOrder, answer.Status, user);
_entities.SaveChanges(); // automatically uses the open transaction instead of a new one
tran.Commit();
}
catch
{
tran.Rollback();
}
finally
{
if (_entities.Connection.State == System.Data.ConnectionState.Open)
_entities.Connection.Close();
_entities.AcceptAllChanges();
}
}
Is your stored procedure doing an explicit commit? Things run in a database session will be available for that session, but not available to any other session until the action is committed.
When you pull data out of your database into your context that data is kept in memory, separate from the actual database itself.
You will see the changes if you create a new context object instance and load the data from the database with it.
It's good practice to not use the same instance of your context object but create them on an as needed basis for individual transactions with the database. In your case if you're updating via function imports instead of the context.SaveChanges() method then you need to refresh your context with the updated data after you commit those changes.
Add this to your connect string (assuming sql 2005)
transaction binding=Explicit Unbind;
if the data is no longer available after session reset, then the problem is indeed with a transaction, if the data is then available after reset, then your problem is something different and we'll likely need more details.

Resources