Using Entity Framework, I have created an application which is able to read data from the database it was modeled against. I now have another database, with the same tables, hosted on another server.
The problem is that the tables on the second database belong to a schema with a different name to the original, so simply changing the connection string for my context in the app.config file doesn't work. (I get the error "table or view does not exist"). There must be some mapping somewhere in the auto generated code stating the original schema name.
What is the correct way to handle this kind of situation?
I don't really want to have to re-model the second database as it is identical to the first.
I can't change the databases as other applications would stop working.
Any nudge in the right direction would be greatly appreciated.
OK, so here's what I've done to solve this.
As #Kelmen mentioned in the comments, opening the EDMX file in a text editor revealed that this is where the schema information is stored. So I think I could have simply cleared out the value of the schema attribute and used the connection string to drive the schema.
This didn't feel right for a couple of reasons:
If the model was refreshed at any point, it might have repopulated the schema names, which would be REALLY annoying. I didn't have time to test if this would actually happen.
This method wouldn't let me control the schema name if I did need to change it at runtime.
The solution was to use Code First and the Fluent API to edit the model configuration in the OnModelCreating event within my derived DbContext class.
I'm now considering modifying my context class so that I can pass in the name of the schema or possibly drive it from my app.config.
I found the links tutorials to be quite useful:
Change Schema of Entity Framework
Entity Framework Change Schema Name Per Connection
Related
Does anyone know if there is a way to use fluent migrator to create schema prefix tables for different users e.g.
UserMachine1 points to a database but their tables are prefixed with UserMachine1.TableName when they run the migrations.
UserMachine2 points to the same database but would generate UserMachine2.TableName in the same database.
As you can see the schema would be machine name specific in our case.
Can this be done in fluent migrator?
if it can how can you define the schema.VersionInfo table prefix. as out of the box, it just puts it under dbo.VersionInfo like all other tables.
Is this even a good idea? as I am not the inventor of this idea, supposedly due to moving to azure databases.
Many thanks for your thoughts and answers, cheers
I found that there was this link that detailed how you might do this https://fluentmigrator.github.io/articles/version-table-metadata.html still not sure it is a good idea, as then you would also have to rename primary keys and constraints if you do provide nicely named ones. Also how would you run custom SQL scripts to run against specific schema ones. All feels like adding extra work which is not giving much value.
i have a UI page which contains, a drop down, with multiple values.
From a UI page, user will select one schema from the drop down, then the data related to that schema should be loaded to a grid. That means in future we may get more number of schema each with the same Oracle database and table structure.
Entity context already created using DB First approach with default config. but based on above requirement, I need to connect to Oracle DB based on Schema change.
While I use below didn't worked for me, It always point to the schema configured at connection string, not the schema that i'm sending to entity context.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (SchemaName != null)
{
modelBuilder.HasDefaultSchema(SchemaName);
}
base.OnModelCreating(modelBuilder);
throw new UnintentionalCodeFirstException();
}
can anybody suggest best way to do it?
I tried by applying schema name at model creation as above code This didn't work for me.
Actual need is, Entity context already created using DB First approach with default config. but based on above requirement, I need to connect to Oracle DB based on Schema change.
I found the solution by adding a helper class which will update the entity context files at run time by replacing the schema.
I just followed the url EF6 Dynamic Schema Change, which works well for me.
I change the connection to use ORACLE, and called this 'connect' method from my service layer.
I suggest you create separate entity context for each Oracle schema. You can use the same Oracle account as long as that account has access to all the schemas (although I think it is way easier to use separate account for each schema). Depending on the schema selected at runtime, it is easy to use the correct entity context with an if-then-else statement. The schema for each entity class is embedded in the .edmx file, there's no worries that the query will fail even if using one Oracle account (provided access was granted).
Of course if you are only using one Oracle account then things gets complicated when creating the initial entity context. One approach is to use the original schema's account (or a temp account) then edit the app.config to the desired Oracle account afterwards or try this approach before removing the logon trigger once done (note: I didn't try this approach as I only tried the former).
Personally, I think having separate entity context for each schema with separate Oracle account is a cleaner and simpler approach rather than updating the entity context file dynamically.
I'm building an application using EF 5 to talk to an existing Oracle database. I'm not allowed to change any part of the DB schema. I have generated my model from the database using the VS2012 wizard, and all classes are named after their Oracle counterparts.
The naming of objects in the database is QUITE_UGLY_AND_INCONSISTENT, so I'd like to rename the POCO classes and properties. I can easily do that from the EDM Designer. As a result, I get neatly named class and property names, that are mapped to the UGLY_NAMED tables from the DB. I can successfully perform queries and everything works smoothly. Exactly what I wanted.
However, when I need to add new tables to the model, I run the "Update Model from Database" wizard and check the additional tables to import. It suddenly lists my renamed (but still correctly mapped) classes under the Delete tab, saying it can't find them in the database. When I click Finish, my existing classes are unmapped and I have to manually re-map each property to its corresponding DB column... Or roll back to the previous version of the EDMX file from version control.
I'm looking for what you think would be the most elegant solution to this problem, since I need the application to be as maintainable as possible. I strongly favour an approach that lets me auto-generate new classes from the database while preserving the existing renamed objects and their mappings.
Am I overlooking some way to prevent the Update Model wizard from deleting my existing mappings?
Should I use a different approach to renaming the generated classes?
Should I leave the generated classes unchanged and instead construct sanely-named wrapper classes that are exposed to the rest of my application?
Should I refrain from auto-generation and instead go for a code-first approach? This is a very unfavorable option, because I need the time spent on manual model coding and mapping to be as little as possible. Adding objects will be a very frequent task.
Should I perhaps even use a different ORM altogether..?
I discovered the culprit myself: running the "Generate Database from Model" wizard due to a recommendation in an article I read somewhere. It changed all the model's underlying table and column names to SQL Server standard names ([dbo].[Customers].[CustomerID] etc.).
I am using Entity Framework code first for the first time in a production environment. Everything went fine until we got the DB up and had put some of the data in it and then to get some of the data we were importing from another location we had to change field lengths. So we made some of the fields nvarchar(99) instead of nvarchar(50).
That went fine and the application still worked but I knew I needed to change the data annotation or it would blow up later when it loaded and tried to save a too long field. When I did that the app blew up even though the model and the db are now matching. So I thought that it was the hash in the metadata table so I thought I'd be clever and make a new DB and take the hash from there and copy it. That did not work and in fact now I cannot get my app to connect to the test db that we have data loaded in at all.
I do not want to drop and recreate this database. I want entity framework to realize that the model and the schema do in fact match. Is there any way for me to do this? Also why did copying the metadata from a DB that entity framework created with this model not work?
Entity Framework Code First creates a EdmMetadata table and saves a hash of your Model classes in it. When you change something in the Model, the hash of the new Model classes doesn't match what's in the EdmMetadata table anymore, and the app should "blow up" at runtime. What you need to do to keep using the same database without dropping it, is to delete the EdmMetadata table. This way EF will not do that check and will try to proceed with the access to the DB.
Check this video tutorial (skip to 8:10 of the "When Classes Change" section).
Sorry I fixed this. Removing the metadata worked. But turns out I had updated to a more recent version of EntityFramework accidentally while trying to fix my problem and this more recent version expected different naming conventions for the Database. In any case recreating the many-to-many group person table with a script from a DB created by Entity Framework and deleting the metadata fixed the problem.
In most asp.net applications you can change the database store by modifing the connectionstring at runtime. i.e I can change from using a test database to a production database by simply changing the value of the "database" field in the connectionstring
I'm trying to change the schema (but not necessarily the database itself) with entity framework but no luck.
The problem I'm seeing is the that the SSDL content in the edmx xml file is storing the schema for each entityset.
see below
<EntitySet
Name="task"
EntityType="hardModel.Store.task"
store:Type="Tables"
Schema="test" />
Now I have changed the schema attribute value to "prod" from test and it works..
But this does not seem to be a good solution.
I need to update evert entity set as well as stored procedures ( I have +50 tables )
I can only do this an compile time?
If I then try to later update the Entity model-entityies that already exist are being read due to EF not recognizing that the table already exists in the edm.
Any thoughts?
I have this same issue and it's really rather annoying, because it's one of those cases where Microsoft really missed the boat. Half the reason to use EF is support for additional databases, but unless you go code first which doesn't really address the problem.
In MS SQL changing the schema makes very little sense, because the schema is part of the identity of the tables. For other types of databases, the schema is very much not part of the identity of the database and only determines the location of the database. Connect to Oracle and changing the database and changing the schema are essentially synonymous.
Update Upon reading your comments it's clear that you're wanting to change the referenced schema for each DB, not the database. I've edited the question to clarify this and to restore the sample EDMX you provided which was hidden in the original formatting.
I'll repeat my comment below here:
If the schemata are in the same DB, you can't switch these at runtime (except with EF 4 code-only). This is because two identically-named and structured tables in two different schemata are considered entirely different tables.
I also agree with JMarsch above: I'd reconsider the design of putting test and production data (or, actually, 'anything and production data') in the same DB. Seems like an invitation to disaster.
Old answer below.
Are you sure you're changing the correct connection string? The connection string used by the EF is embedded inside the connection string which specifies the location of CSDL/SSDL/etc. It's common to have a "normal" connection string for use by some other part of your app (e.g., ASP.NET membership). In this case, when changing DBs you must update both of your connection strings.
Similarly, if you update the connection string at runtime then you must use specific tools for this, which understand the EF connection string format and are separate from the usual connection string builder. See the example in the link. See also this help on assigning EF connection strings.
The easiest way to solve the problem is to manualy remove all entries like 'Schema="SchemaName"' from the SSDL part of the model.
Everything works propely in this case.
Sorry its not a robust answer but I found this project on codeplex ( as well as this question ) while googling around for a similar problem:
http://efmodeladapter.codeplex.com/
The features include:
Run-time adjustment of model schema,
including:
Adjusting data-level table
prefixes or suffixes
Adjusting the
owner of database objects
Some code from the docs:
public partial class MyObjectContext : BrandonHaynes.ModelAdapter.EntityFramework.AdaptingObjectContext
{
public MyObjectContext()
: base(myConnectionString,
new ConnectionAdapter(
new TablePrefixModelAdapter("Prefix",
new TableSuffixModelAdapter("Suffix")),
System.Reflection.Assembly.GetCallingAssembly()))
{
...
}
}
Looks like its exactly what your looking for.
The connection string for EF is in the config file. There is no need to change the SSDL file.
EDIT
Do you have the prod and test schema in the same database?
If Yes you can fix it by using a seperate database for prod and test. Using the same schema name in both databases.
If No you can fix it by Using the same schema name in both databases.
If you will absolutly have different schema names, create two EF models, one for test and one for prod, then select which on to use in code based on a value in your config file.
When I create a new "ADO.NET Entity Data Model", there are two properties "Entity Container Name" and "Namespace" available for editing in design view.. Using the namespace.EntityContainerName, you can create a new instance specifying a connection string.
MyEntities e = new MyEntities("connstr");
e.MyTable.Count();
I'm not sure if this helps you or not, good luck!
Also, this is a good case for multiple layers (doesn't have to be projects, but could be).
Solution
* DataAccess - Entities here
* Service - Wraps access to DataAccess
* Consumer - Calls Service
In this scenario, the consumer calls service, passing in whatever factor determines which connection string is used. The service then instantiates an instance of data access passing in the appropriate connection string and executes the consumer's query.
Here is a similar question with a better answer:
Changing schema name on runtime - Entity Framework
The solution that worked for me was the one written by Jan Matousek.
Solved my problem by moving to sql server and away from mysql.
Mysql and Mssql interpret "schemas" differently. Schemas in mysql are the same/synonyms to databases. When I created the model the schema name..which is the same as the database name is hard coded in the generated model xml. In Mssql the schema is by default "dbo" which gets hard coded but this isnt an issue since in mssql schemas and databases are different.