DbContext.SaveChanges Fails to Save Valid Entities - entity-framework-5

I'm using EF 5 with Code First POCO.
Here is the repository's SaveChanges implementation:
public virtual List<DbEntityValidationResult> SaveChanges()
{
var errors = new List<DbEntityValidationResult>();
try
{
DbContext.SaveChanges();
}
catch (DbEntityValidationException ex)
{
errors.AddRange(ex.EntityValidationErrors);
}
return errors;
}
A single validation error causes no entities to be written to the database. I had expected valid entities to be written out and to receive errors for invalid entities.
Is this how EF is supposed to act?

That's the way EF works.
SaveChanges() creates a transaction and attempts to save all the changes in the context.
If any writes fail for any reason, the whole transaction is rolled back and no changes are persisted.

I did some more digging. EEF does not attempt to write the Entities. It calls validation from the Object Context first. If any entities fail, they are added to DbValidationResult and the save is canceled.
For bulk transactions, you can remove those entities and handled any errors and then resave.
Once all the Entities validate, EF writes changes to the database as appropriate.

Related

Azure Storage Tables - Update Condition Not Satisfied

I'm getting a random Exception when I try to update an entity on a storage table. The exception I get is
System.Data.Services.Client.DataServiceRequestException: An error occurred while processing this request. ---> System.Data.Services.Client.DataServiceClientException: {"odata.error":{"code":"UpdateConditionNotSatisfied","message":{"lang":"en-US","value":"The update condition specified in the request was not satisfied.\nRequestId:2a205f10-0002-013b-028d-0bbec8000000\nTime:2015-10-20T23:17:16.5436755Z"}}} ---
I know that this might be a concurrency issue, but the thing is that there's no other process accessing that entity.
From time to time I get dozens of these exceptions, I restart the server and it starts working fine again.
public static class StorageHelper
{
static TableServiceContext tableContext;
static CloudStorageAccount storageAccount;
static CloudTableClient CloudClient;
static StorageHelper()
{
storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudClient = storageAccount.CreateCloudTableClient();
tableContext = CloudClient.GetTableServiceContext();
tableContext.IgnoreResourceNotFoundException = true;
}
public static void Save(int myId,string newProperty,string myPartitionKey,string myRowKey){
var entity = (from j in tableContext.CreateQuery<MyEntity>("MyTable")
where j.PartitionKey == myId
select j).FirstOrDefault();
if (entity != null)
{
entity.MyProperty= myProperty;
tableContext.UpdateObject(entity);
tableContext.SaveChanges();
}
else
{
entity = new MyEntity();
entity.PartitionKey =MyPartitionKey;
entity.RowKey =MyRowKey;
entity.MyProperty= myProperty;
tableContext.AddObject("MyTable", entity);
tableContext.SaveChanges();
}
}
The code you've posted uses the very old table layer which is now obsolete. We strongly recommend you update to a newer version of the storage library and use the new table layer. See this StackOverflow question for more information. Also note that if you're using a very old version of the storage library these will eventually stop working as the service version they're using is going to be deprecated service side.
We do not recommend that customers reuse TableServiceContext objects as has been done here. They contain a variety of tracking that can cause performance issues as well as other adverse effects. These kind of limitations is part of the reason we recommend (as described above) moving to the newer table layer. See the how-to for more information.
On table entity update operations you must send an if-match header indicating an etag. The library will set this for you if you set the entity's etag value. To update no matter what the etag of the entity on the service, use "*".
I suggest you can consider using the Transient Fault Handling Application Block from Microsoft's Enterprise Library to retry when your application encounters such transient fault in Azure to minimize restarting the server every time when the same exception occurs.
https://msdn.microsoft.com/en-us/library/hh680934(v=pandp.50).aspx
While updating your entity, set ETag = "*".
Your modified code should look something like this -
if (entity != null)
{
entity.MyProperty= "newProperty";
tableContext.UpdateObject(entity);
tableContext.SaveChanges();
}

Alternate Causes for "'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores.'"

thanks for reading. We've recieved crash reports on our iOS app with the following error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation.'
This occurs when our main queue NSManagedObjectContext attempts to save:
BOOL saved = [managedObjectContext save:&error];
Which occurs in a block submitted via:
[managedObjectContext performBlockAndWait:saveBlock];
The internet (especially SO) is full of explanations for this error suggesting that we never had a persistent store cooridinater (that we failed to create it properly when we built the core data stack). However, it's difficult to see how we could get to this point in program execution without a persistent store coordinator. For kicks, i commented out the line where we set the persistent store and the app crashes almost immediately (without getting to our save method).
Does anyone know if there's an alternate cause for this exception or is it ALWAYS because there is no persistent store? Is there any way to lose a persistent store?
A little more color: we use parent/child NSManagedObjectContexts in order to load data in a background thread. The full save method looks like this:
-(void)saveWithManagedObjectContext:(NSManagedObjectContext*)managedObjectContext successHandler:(void (^)())successHandler failureHandler:(void (^)(NSManagedObjectContext* managedObjectContext, NSError*))failureHandler
{
void(^saveBlock)() = ^() {
NSError *error = nil;
BOOL saved = [managedObjectContext save:&error];
if (!saved) {
if (error != nil) {
NSLog(#"Unresolved error saving %#, %#", error, [error userInfo]);
}
failureHandler(managedObjectContext, error);
} else {
if (managedObjectContext.parentContext != nil) {
[self saveWithManagedObjectContext: managedObjectContext.parentContext successHandler:successHandler failureHandler:failureHandler];
} else {
successHandler();
}
}
};
BOOL isMainContext = managedObjectContext.parentContext == nil;
if (isMainContext) {
[managedObjectContext performBlockAndWait:saveBlock];
} else {
[managedObjectContext performBlock:saveBlock];
}
}
It can be called from a background thread which will call save: on the NSManagedObjectContext via a performBlock: and then rescursively call this method on the parent NSManagedObjectContext in order to save it. When the app crashes, it's always on the main thread which makes sense because the main queue context is the only one that needs a persistent store.
Many thanks for any help. I did cross post to devforums.apple.com, so my apologies if you've seen this twice.
There are basically two places to look.
First, check what happens when you first add the persistent store to the Core Data stack. That would be in the app delegate if you are using the Apple template, but typically somewhere in your code when the app is initialized there is a call to
addPersistentStoreWithType:configuration:URL:options:error:.
Second, as you mention background threads and because you are passing a managed object context to your method, you possibly have child contexts. Check that you have properly assigned either a valid parent context or the store coordinator to the child context when you create it.
This error is unfortunately ambiguous. I have seen it when using configurations and there is a typo in the configuration name or in one case where a configuration name was passed in when there were no configurations in the model.
So my first line of testing would be to look at your Core Data stack creation code. Can you add that to your question so we can take a look at it?
I corresponded offline with Tom Harrington who made the innocuous comment: "Persistent stores shouldn't go away unless you remove them (and I'm assuming you don't do that)." 'course i DO do that when i tear down the core data stack (when a user logs out.) When i tear down the stack, i call reset on my root managed object context (the only one i have a reference to) and then remove the persistent store. However, if there are pending changes in a child context, they'll propagate up to my now persistentstoreless root context causing the crash on save. Since there's a good reason why parent contexts don't keep track of their children, i don't want to keep track of them either. Instead i just confirm that there is either a parent context or a persistent store coordinator (with at least one store) before calling save.

Entity Framework Code First check Database exist

In Entity Framework Code first i want to check database is exist before create Database.
In code first when i call Entities dc = new Entities() then it goes to OnModelCreating and generate Database. How can i check if the Database exists in Entity framework Code first?
You can do:
using(var dbContext = new MyContext())
{
if (!dbContext.Database.Exists())
dbContext.Database.Create();
}
Edit:
Following the colegue sugestion, the meaning of this code is very simple: Supose your context constructor is not set to create the database, so before sending any database operations, you can check if it exists, if not, you can create a new one with the connection string parameters being the rules for the creation.
This would be a static alternative, that works even without creating the DbContext first:
System.Data.Entity.Database.Exists(dbNameOrconnectionString);

Entity Framework Check for references before deleting

Say I have a User that I want to delete, but the User might be referenced by other tables in the database. Is there a way to check for references to this user before trying to delete or is the best option to just delete and catch/handle the exception that SaveChanges() throws?
Obviously I could check each table where the user might be referenced...but I would rather not as it is referenced in a few places and it just seems like a messy way to do things.
I don't now if you have found a solution to this yet but I'm posting since i run into a similar problem myself. I suppose you could use a query to check for references lets say something like..
bool related = db.Article.Where(i => i.CategoryId == id).Any();
But i believe it is better to catch the exception than to check for references.
For scenarios where you want a required relationship but no cascade delete you
can explicitly override the convention and configure cascade delete behavior with the
Fluent API.
The Fluent API method to use is called WillCascadeOnDelete and takes a Boolean as a
parameter. This configuration is applied to a relationship, which means that you first
need to specify the relationship using a Has/With pairing and then call WillCascadeOn
Delete. Something like:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Article>()
.HasRequired(a => a.Category)
.WithMany(i => i.Articles)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
Then you usually get a DbUpdateException or a InvalidOperationException depending on how your data is loaded into memory. You can catch them with a simple statement and add a message to the user.
try
{
db.Category.Remove(category);
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DataException)
{
ModelState.AddModelError("", "Your message here");
return View(category);
}
What WillCascadeOnDelete basically does is that it changes the Delete rule in your database from Cascade to No Action which causes the error to be thrown when a violation occurs.
The overall message here is that you have control over the cascade delete setting, but
you will be responsible for avoiding or resolving possible conflicts caused by
not having a cascade delete present. It worked for me, hope it helps you too.
See also:Configuring Relationships with the Fluent API

Ncqrs: How to raise an Event without having an Aggregate Root

Given I have two Bounded Contexts:
Fleet Mgt - simple CRUD-based supporting sub-domain
Sales - which is my CQRS-based Core Domain
When a CRUD operation occurs in the fleet management, an event reflecting the operation should be published:
AircraftCreated
AircraftUpdated
AircraftDeleted
etc.
These events are required a) to update various index tables that are needed in the Sales domain and b) to provide a unified audit log.
Question: Is there an easy way to store and publish these events (to the InProcessEventBus, I'm not using NSB here) without going through an AggregateRoot, which I wouldn't need in a simple CRUD context.
If you want to publish the event about something, this something probably is an aggregate root, because it is an externally identified object about a bundle of interest, otherwise why would you want to keep track of them?
Keeping that in mind, you don't need index tables (I understand these are for querying) in the sales BC. You need the GUIDs of the Aircraft and only lookups/joins on the read side.
For auditing I would just add a generic audit event via reflection in the repositories/unit of work.
According to Pieter, the main contributor of Ncqrs, there is no way to do this out of the box.
In this scenario I don't want to go through the whole ceremony of creating and executing a command, then loading an aggregate root from the event store just to have it emit the event.
The behavior is simple CRUD, implemented using the simplest possible solution, which in this specific case is forms-over-data using Entity Framework. The only thing I need is an event being published once a transaction occurred.
My solution looks like this:
// Abstract base class that provides a Unit Of Work
public abstract class EventPublisherMappedByConvention
: AggregateRootMappedByConvention
{
public void Raise(ISourcedEvent e)
{
var context = NcqrsEnvironment.Get<IUnitOfWorkFactory>()
.CreateUnitOfWork(e.EventIdentifier);
ApplyEvent(e);
context.Accept();
}
}
// Concrete implementation for my specific domain
// Note: The events only reflect the CRUD that's happened.
// The methods themselves can stay empty, state has been persisted through
// other means anyway.
public class FleetManagementEventSource : EventPublisherMappedByConvention
{
protected void OnAircraftTypeCreated(AircraftTypeCreated e) { }
protected void OnAircraftTypeUpdated(AircraftTypeUpdated e) { }
// ...
}
// This can be called from anywhere in my application, once the
// EF-based transaction has succeeded:
new FleetManagementEventSource().Raise(new AircraftTypeUpdated { ... });

Resources