Entity Framework savechanges - can't see changes in other clients - c#

I'm using EF 4.0 with VS2010. I have 2 clients running my applicaion.
When I save the changes in one client, I see them in the SQL server, but the 2nd client doesn't see them.
I need to restart the application to see the changes.
I'm using a Data layer for all the DB stuff, I leave my connection open all the time (as suggest in some post I read) might it be the problem??? any workaround I can't write the DL from scratch again.
10x

By default if an entity is loaded to the context that instance is returned when you query the database for a set of entities which will include the above entity.
You need to set the MergeOption to OverwriteChanges to get the changes in the database.
context.Products.MergeOption = MergeOption.OverwriteChanges;
var products = context.Products.Where(/**/);
Its better to create short lived to contexts to avoid such problems.

EntityFramwork isn't updating data when you change it on other connection. To get new state you have to recreate Context and load all data again.

Related

Make desktop client work with newer EF db migration without updating

Currently I have an ERP which is a Winforms based client (with SQL Server), which gets delivered and updated on desktops using ClickOnce.
The current version is using Entity Framework 4 (ObjectContext-based) and database first. The way I am doing updates to the client when there's a database schema change is a four step process:
Create an intermediary updated database schema on production with compatible columns (allow null everywhere or have a default value, etc.). Old clients can connect to that database and keep working as if nothing was changed
Update desktop clients to an intermediary version with the updated features which accounts for this intermediary schema but has all "final schema" features
Once all clients are updated and all records are compatible with the "final" schema, make a new update on the schema with the needed database constraints
Update all clients to a final version which is mapped to this final schema (which accounts for database constraints errors, and need those schema changes to work).
I've found this process to be, if a bit cumbersome to us, better for the clients, who can update when they see fit, and don't get interrupted with an update in the middle of their work (which may involve having customers in front of them who don't want to wait for a software update).
Now I have made an almost-complete rewrite of the client (still Winforms), using EF6 and code-first, with migrations.
I've been searching for documentation but can't find anything (seems there's only web programming these days, where generally updates to the database and the web client can be done simultaneously and without interrupting users), but once I apply migrations on production, non-updated clients can no longer work with the database. EF will complain and throw exceptions upon instantiating the context if it's not up to date with the database schema.
Specific question: is there a way to have an EF6 code-first dbcontext to work with a newer migration of the database schema than the one compiled-in, as long as it is compatible? If that's the case, I could just keep doing what I was doing so far.
And an (I guess) oppinion based question if anyone wants to extend on the actual answer: is there any better way to handle this scenario? I'm sure I'm not the only one having this problem, however the keywords needed to Google for documentation are too broad and so far, only web scenarios have come up on my searches.
I'm currently at a stage on the client rewrite where major changes could be allowed, so I don't care if the solution may complicate parts of the code
When an application initializes the model database, etiher by directly calling DbContext.Database.Initialize or instancing the first DbContext, it checks if the model in the application and the model in the database match.
To do so, it calculates the model hash, and compares it with the hash stored in the __MigrationHistory table (or in the EdmMetadata table, if it was updated from EF 4.x). This is done in the System.Data.Entity.Internal.ModelCompatibilityChecker.CompatibleWithModel method, which receives a parameter named throwIfNoMetadata which happens to be false in the internal implementation, so no exception is thrown if there is no metadata.
So, if you make this tables dissapear in some way before the database is initialized, you'll avoid the error. The important point is that you must do this change without using DbContext. If not, the database will try to initialize, and, if this table exists, it will fail. So you can use plain ADO.NET to drop the tables.
Take into account that the metadata tables can be automatically created, for example by applying migrations.
You can also use ctx.Database.CompatibleWithModel(true) to check if the database metadata exists and is compatible or not, to get rid of it. The parameter is precisely the throwIfNoMetadata that I mention above.
Compatibility check in db initializers:
The default DB Initializer is CreateDatabaseIfNotExists, and it does check the model compatibilty with the throwIfNoMetadata set to false. That's why this solution works. However, if you implement your own version of DB Initializer that doesn'd run the check, it shuld work.
public virtual void InitializeDatabase(TContext context)
{
Check.NotNull(context, "context");
var existence = new DatabaseTableChecker().AnyModelTableExists(context.InternalContext);
if (existence == DatabaseExistenceState.Exists)
{
// If there is no metadata either in the model or in the database, then
// we assume that the database matches the model because the common cases for
// these scenarios are database/model first and/or an existing database.
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false, existenceState: existence))
{
throw Error.DatabaseInitializationStrategy_ModelMismatch(context.GetType().Name);
}
}
else
{
// Either the database doesn't exist, or exists and is considered empty
context.Database.Create(existence);
Seed(context);
context.SaveChanges();
}
}

Revert the changes in database using Entity Framework

I am using SQL Server as my back end database and Entity Framework 6 to access it.
I want to undo all the changes done to the database by a method. The method makes several calls to 4 different databases and thus 4 different contexts. I am not able to keep track of changes to revert them at the end.
I am aware of context.ChangeTracker.Entries() that keeps record of DB changes. But I am unable to utilize it because changes are lost as soon as a context goes out of scope. And I need need to revert the changes at the end of methods after accessing all 4 databases.
You should use transactionScope or beginTransaction, here you can get some basic information on both topics to get you started and here you can learn about the difference between them which will help you choose the right one for you.

How to rename database and files with entity framework

I'm building a patch-application that modifies an existing MS SQL database. There are multiple steps the user goes through during the patch, but no changes are made till the end.
The program uses Entity Framework in order to read and write data to the database, and i'm collecting all changes within a single transaction so that i can rollback any time.
However, now i need to be able to rename the database on the SQL Server (and it's files)... Is this achievable with Entity Framework, to be contained within the same transaction as the other operations? If yes, how? And will the connection be broken once the database is renamed?
EF is not able to do that. Use SMO, it has Database.Rename method and it is much more appropriate tool to work with db schema:
Server srv = new Server(conn);
Database database = srv.Databases["AdventureWorks"];
database.Rename("newName");

Synchronizing Entire Databases using Microsoft Sync Framework 2.1

I need the ability to sync multiple remote databases, upload and download, with my main database.
However, the problem lies in the fact that I need to sync the entire database, and the database schema is going to be being updated constantly, and I didn't see any way to code it to grab the entire database schema without adding each individual table to the SyncScope.
This is problematic as that scope will always be changing. I solved the initial problem of removing the existing scope, and adding a new one, but I still cannot find any simple solutions, without querying system tables, and parsing the results, and passing those results (for 150+) tables back to my SyncScope.
The reasons I originally looked at Sync Framework are:
I need to be able to manage the direction of the sync (upload/download) when I do a sync programatically from C# on a button click.
I need the ability to turn on that button, based off their network connectivity.
There's additional tasks that need to be done on a sync download, such as changing connection strings of the mobile units, and storing information about their connection and unit in the database.
There's additional tasks that need to be run on a sync upload, such as verifying data against customer business rules through my OR/M, archiving the data to a network storage, restarting the application, and changing connection strings again.
Eventually, I need partial data sets, decided/chosen by the customer, at run-time, at the object level, in an OR/M framework. These objects, may coincide with one or more tables I won't know of at design-time, or may not even exist at design-time.
Does anyone know if another framework encompasses all my requirements, or if there is a simpler way to do this in the sync framework?
For this task, especially with a changing schema, you could consider Merge Replication instead of the Sync framework.

Entity Framework Concurrency

I am developing application that works with sql server, I read and update data from (by) multiple sources.
Because of that, there is a problem that one updates already updated data....
How can I deal with that issue?
(I know EF has built in Concurrency mode but if I understand right, if my design creates and disposes contextobject every time this won't work)
The secret is normally to use a timestamp field and check that against the value in your object before you commit to the db. There's an article about this subject here.

Categories