Multiple entity framework 6 contexts in oracle throw ORA-00955 - oracle

I am using Entity Framework 6.1.3 connecting to an oracle database.
I am trying to use multiple contexts with the same schemaName for oracle. But when I create the contexts it appears they share the __MigrationHistory table and when the second context attempts to create itself it throws "ORA-00955: name is already used by an existing object". To be clear the two contexts I attempted to split by domain design and do not share any entities between the two.
This is the code I'm attempting to run, and it works fine when I run it against SQL Server. But Oracle throws the ORA-00955 error.
try
{
using (var hContext = new HContextORCL(connectionString, "SchemaName"))
using (var aContext = new AContextORCL(connectionString, "SchemaName"))
{
hContext.Database.Initialize(true);
aContext.Database.Initialize(true);
}
}
I've tried using CreateIfNotExists() instead of the Initialize but receive the same error. I have tried setting both contexts Database.SetInitializer<context>(null); because I don't need the migrations at this point. But that doesn't seem to work either.
Ideally I would like to keep the __MigrationHistory table and have both my contexts initialized in Oracle. But that's not necessary. I can sense myself going off the rails trying to figure out all these work-arounds which when I look at them seem overly complicated for something that works in SQL Server.
I am at a loss how to intialize two contexts with the same schema name in an oracle database.

Alright, for better or worse this is the work around I'm going with. My issue appears to be the MigrationHistory table is shared between the two contexts.
Entity Framework 6 allows you to manipulate the migration table using the System.Data.Entity.Migrations.History namespace (Migrations.History Namespace).
So I open the migrations table, copy all the history rows out, delete the migration table, perform my second context initialization and copy the history rows back into the migration database (created during the second context initialization).
try
{
var dbConnection = new OracleConnection(connectionString);
using (var migrationContext = new Migrations.History.HistoryContext(dbConnection, "SchemaName"))
using (var hContext = new HContextORCL(connectionString, "SchemaName"))
using (var aContext = new AContextORCL(connectionString, "SchemaName"))
{
hContext.Database.Initialize(true);
List<HistoryRow> currentHistory = migrationContext.History.ToList();
migrationContext.Database.Delete();
aContext.Database.Initialize(true);
currentHistory.ForEach(rowItem => migrationContext.History.Add(rowItem));
migrationContext.SaveChanges();
}
}

Related

Cleanest way to change database schema in EF6

Currently we are writing a page in mvc5, with an oracle sql database connected with entitiy framework 6.
We currently have two schemas in the oracle database, one for testing and the other for development. The model in entitiy framework is generated from the development database, and works perfectly with it.
The problem comes, when changing the connection string to the testing schema. When the connection string is changed the application is unable to locate the tables (as they still reference the development schemes).
Currently I can fix this, by deleting all the tables from the model, and recreating the model from the correct schema, or manually editing every file referencing the schema. Both solutions are kinda tiresome and error prone.
How is this scenario usually dealt with?
EDIT
It seems that changing the database and retaining the schema, does not produce any error. So this is only schema related.
I guess this is a perfect use case for using entity framework command interceptors. I just tried and it works perfectly, even for Entity Framework DB-First approach.
You can register a custom command interceptor like this:
DbInterception.Add(new ReplaceSchemaInterceptor(newSchema: "[my]"));
This line will replace [dbo] schema name with the [my] schema name, before the query reaches the database. Luckily, schema name is enclosed with square brackets when Entity Framework generates the command text, so it's easy to match and replace. BTW, I'm not an Oracle expert, so I'm assuming that Oracle queries also include schemas in the same format. If not, then maybe you will have to tweak the implementation a bit (to replace the schema from whatever format it is generated by EF).
ReplaceSchemaInterceptor is a class that implements IDbCommandInterceptor interface. Inside this class, you need to replace the schema with your own schema. Below is the implementation of this class:
class ReplaceSchemaInterceptor : IDbCommandInterceptor
{
private readonly string _newSchema;
public ReplaceSchemaInterceptor(string newSchema)
{
_newSchema = newSchema;
}
public void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void NonQueryExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
command.CommandText = command.CommandText.Replace("[dbo]", _newSchema);
}
public void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
}
public void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
command.CommandText = command.CommandText.Replace("[dbo]", _newSchema);
}
public void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
public void ScalarExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
command.CommandText = command.CommandText.Replace("[dbo]", _newSchema);
}
}
And lastly, the code is not perfect. You need to add some null checks for the constructor parameters, and maybe get rid of the code duplication inside implementation methods when replacing command text (extract into reusable method?). Right now it just does what you had asked for.
With fluent mappings in Entity Framework code-first you can indicate the default schema at runtime. This is one statement in OnModelCreating in your DbContext subclass, for instance:
modelBuilder.HasDefaultSchema("dev");
You're used to regenerating the model from the database, from which I conclude that the model doesn't contain many (or any) customizations that would make model generation a painstaking operation. This also should make it relatively easy to move to code-first. So I'd recommend you do that.
In Visual Studio, you can generate a code-first model from an existing database by adding an "ADO.Net Entity Data Model" from the templates that come with Entity Framework tools for Visual Studio. (Probably pre-installed). Choose the option "Code First from database" and follow the guidelines.
If you do that, you'll find a connection string in the project containing the model. This connection string may serve as template for the connection string you will put in the config file of your executing assembly. You'll notice that it doesn't look like...
metadata=res://* ... provider=System.Data.SqlClient;provider connection string="...""
This is the connection string that belongs to a database-first edmx model. It contains a path to the metadata files that are generated as resources into the assembly. Instead, the connection string will be a simple ADO.Net connection string. With code-first, EF will generate the meta data at runtime.
If you have this, you can add an entry in your config file for the default database schema and use that to set the schema as I showed above.
It looks like something we are doing here at my workplace.
Use synonyms for your objects!
A possibility would be to create synonyms dynamically for your test tables - and remove references to schema in your files
Say the user that connects is CONNECT_USER - must be different user as the schemas you're using which are SCHEM_DEV and SCHEM_TEST.
Here is how I would do the switch (Oracle PL/SQL scripting - connected as CONNECT_USER):
begin
for x in (select * from all_tables where owner='SCHEM_DEV')
loop
--- drop synonyms on SCHEM_DEV objects
execute immediate 'drop synonym '||table_name ;
--- create synonyms on SCHEM_TEST objects
execute immediate ' create or replace synonym '||table_name||' for SCHEM_TEST.'||table_name ;
end loop;
end;
/

EntityFramework Saga persistance recreate schema in existing DB

I am using MT v3.0.17 with Automatonymous,
I noticed that the table of instance state isn't created if the database already exists. Since I'm directing multiple different automatonymous state machines to the same database, I would like to instruct it to create tables even if database exists.
How can this be done?
Thanks
If you are using Entity Framework, you use migrations to create/update the database and associated tables, as documented by Microsoft:
https://msdn.microsoft.com/en-us/data/dn579398.aspx
If you are using NHibernate, you can use the Schema validation methods, which will verify and update the schema as needed. This is done in the unit tests, as shown:
https://github.com/MassTransit/MassTransit/blob/develop/src/MassTransit.AutomatonymousIntegration.Tests/SqlLiteSessionFactoryProvider.cs#L104
Inspired from the unit tests of masstransit itself, we use EF migrations, and explicitly as EF to apply said migrations during start-up
public static void Main()
{
var saga = new MySaga();
var contextFactory = new SagaWithDependencyContextFactory();
using (var context = contextFactory.CreateDbContext(Array.Empty<string>()))
{
context.Database.Migrate();
}
Func<DbContext> sagaDbContextFactory = () => contextFactory.CreateDbContext(Array.Empty<string>());
var efSagaRepository =
new EntityFrameworkSagaRepository<MySagaInstanceState>(sagaDbContextFactory);
// .. create bus etc..

Replacing EF4.1 with ADO.net when calling stored proc in MVC3?

I need to replace EF4.1 with ADO.NET. The data in our application is returned by stored procedures only. I need help re-writing calls like the following (in order to write a DAL for the application):
EF calling stored procedure:
using (var db = new NexGenContext())
{
SqlParameter param = new SqlParameter("#ReviewID", Id);
var issues = db.Database.SqlQuery<QuestionIssue>(
"SP_GetQuestionIssues #ReviewID", param).ToList();
return View(issues);
}
What is the equivalent in ADO.NET? Get data from the database and map to my models?
The closest ADO.NET technology to being an ORM without actually crossing the line is data sets. Data sets act very much like an ORM in the way you can access data directly from a table without looping through a cursor. Data Sets return lists directly and can track new data vs old.
This link is a pretty good overview:
http://www.c-sharpcorner.com/UploadFile/718fc8/working-with-dataset-in-ado-net/
This MVC datasets with viewbags stack thread specifically addresses using Data Sets in Models.

Entity Framework get entity via variable

I have a listbox populated with table names. I want to be able to click a row in the listbox and return all records from that table and bind to a datagridview. Using good old fashioned SQL this is a piece of cake. Attempting to do the same with Entity Framework 4.3.1 is another matter.
For instance, is there a way to represent "get_picklist_names_v" as a variable in this code below?
static class EfHelper
{
public static EfEntities CreateContext()
{
EfEntities context = new EfEntities();
return context;
}
}
using (var context = EfHelper.CreateContext())
{
IList list = context.get_picklist_names_v.ToList();
lboPicklist.DataSource = list;
lboPicklist.DisplayMember = "name";
}
Entity Framework abstact the SQL stuff with types and does its best so you don't have to write sql for each server flavor (Oracle, SQL Server, MySQL, etc.). That's what an ORM does...
If your used to generic types its quite trivial to do the same with Entity Framework.
It's not exactly what yor looking for but maybe you can find some hints from the followig article :
Repository Pattern with Entity Framework
Entity Framework is not the best tool to achieve this. You could try Entity Sql, but the problem is that in order to use that in a dynamic way you have to capture the results in an IEnumerable<DbDataRecord>. A DataGridView won't display that as such.
There is nothing more convenient for this than filling a DataSet by a TableAdapter and a sql statement. I would stick to that if I were you.

Getting A LINQ .InsertOnSubmit To Work

I'm trying to get an insert to work using LINQ and am having some difficulties.
I am using this example to base my code: http://msdn.microsoft.com/en-us/library/bb763516.aspx
I have my data object set up, but don't know what's going on when db.Orders.InsertOnSubmit is executed.
How can I create this db object to insert a data object into my database using InsertOnSubmit?
edit: Here is some code that I'm working with (It's probably a world of wrong, I'm pretty much fumbling in the dark at this point). I'm super new to database objects, so the whole concept is a bit confusing for me.
var Data = new Data();
Data.value1 = 1;
var db = new dbo(connectionString);
db.InsertOnSubmit(Data);
You need to do more than just call InsertOnSubmit(). You also need to call SubmitChanges(). The reason these are separate steps is to allow you to have multiple inserts, updates and deletes and then submit them all at once via SubmitChanges().

Resources