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..
Related
I wrote small UDF (based on docs page):
function greeting() {
const db = require('#arangodb').db;
let result = db._query('for d in docs FILTER p.id == "123" return d').toArray()[0]
return result;
}
module.exports = greeting;
The problem that it work only with default _system db. How to specify another?
I found mention in docs:
Changing the database might be disallowed in some contexts, for example server-side actions (including Foxx).
So it's impossible?! it's absurd!
From the docs:
Internally, UDFs are stored in a system collection named _aqlfunctions of the selected database. When an AQL statement refers to such a UDF, it is loaded from that collection. The UDFs will be exclusively available for queries in that particular database.
If you have a database myDB, then make sure to register the UDF for that database:
arangosh --server.database myDB ...
or connect to the default database and switch to the right one:
db._useDatabase("myDB");
aqlfunctions.register(...);
You cannot access different databases from within a UDF, it is restricted to the current database by design - it is an extension mechanism for AQL, which is executed in the context of a single database.
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();
}
}
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;
/
I am using Entity Framework Code Fist with migrations. I have a problem that migrations are bound with concrete DB schema. This is not such a problem with MS SQL. But in Oracle: schema = user. So my data model is bound with a DB User that can change.
When I change default schema with modelBuilder.HasDefaultSchema("SCHEME_NAME") I have to generate a new migration but I want to be able to deploy my app to any DB user in Oracle without having to change code and recopmile the project.
Well, you have multiple options for achieving this, such as:
Using automatic migrations and making the
modelBuilder.HasDefaultSchema(dbUserName) functions use an input
parameter. But this has multiple disadvantages such as not being
able to create migrations, instead every time it is automatically
created which has limits when deploying (not being able to create
scripts from it for deploy etc.)
You can implement a custom migration step which inherits from the CreateTableOperation class but as an input it does not take ("SCHEMA_NAME.TABLE_NAME" ...) but "TABLE_NAME" and dynamically gets the schema name when it is run (see one of my post about creating a custom migration operation to get the general idea)
Retrieving the user schema name and concatenating at migrations.
If you want the fastest solution I would choose the third option, which would simply look like this:
var schemaName = MigrationHelper.GetUserSpecificSchemaName();
CreateTable(String.Format("{0}.People", schemaName),
c => new
{
Id = c.Int(nullable: false, identity: true),
})
.PrimaryKey(t => t.Id);
Because don't forget that basically the code in these migrations run just like any other C# code, which is invoked through the Add-Migration PowerShell script method.
For implementing the GetUserSpecificSchemaName you can use ADO.NET that retrieves it from your Oracle database.
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.