EF and Code First Migrations with MySQL - dbo.tablename does not exist - mysql

I have set up entity framework to use MySQL and created a migration.
When I run update-database I get error "table dbname.dbo.tablename' does not exist. Running in -Verbose mode I see the statement that causes the error :
alter table `dbo.Comments` drop foreign key `FK_dbo.Comments_dbo.Comments_Comment_ID`
When I run the query direct in MySQL workbench is throws the same error.
The problem seems to be the dbo. prefix in the migration set. Anything in the form dbo.tablename won't run saying that table does not exist. E.g. select * from dbo.tablename fails but select * from tablename works. The database was generated by Entity Framework and the code first migrations were generated by EF too.
However the migrations generate everything with the dbo. prefix, which does not work.
Does anyone have a solution to this?

I was having this problem just today as well; found my answer here:
MySqlMigrationCodeGenerator
You have to set:
CodeGenerator = new MySqlMigrationCodeGenerator();
In your context's configuration class. This will get rid of the schema gibberish for MySQL. My Configuration class looks like this:
internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("MySql.Data.MySqlClient", new MySqlMigrationSqlGenerator());
SetHistoryContextFactory("MySql.Data.MySqlClient", (conn, schema) => new MySqlHistoryContext(conn, schema));
CodeGenerator = new MySqlMigrationCodeGenerator();
}
}

I have this same issue and I applied the solution posted by Sorio and It generated a lot of problems.
CodeGenerator = new MySqlMigrationCodeGenerator();
This code line can change all the sql that you generate, for example in my case in the sql code to apply to the database all the foreign key constraints disappear.
I am still without a solution because for me this is not acceptable and I recommend you to check the sql generate with the command before use this solution:
update-database -script

Related

For django testing, how do I use keepdb with mariadb

I have a database with a lot of nonmanaged tables which I'm using for a django app. For testing I'm wanting to use the --keepdb option so that I don't have to repopulate these tables every time. I'm using MariaDB for my database. If I don't use the keepdb option everything works fine, the test database gets created and destroyed properly.
But when I try to run the test keeping the database:
$ python manage.py test --keepdb
I get the following error:
Using existing test database for alias 'default'...
Got an error creating the test database: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CREATE DATABASE IF NOT EXISTS test_livedb ;\n SET sql_note' at line 2")
I assume that this is an issue with a different syntax between MariaDB and MySQL. Is there anyway to get the keepdb option to work with MariaDB?
thanks very much!
For what it's worth: This bug was introduced in Django 2.0.0 and fixed in Django 2.1.3 (https://code.djangoproject.com/ticket/29827)
Two things - check out Factory Boy (for creating test data) and I would suggest checking out Pytest as well. With non-managed tables, the issue I think you'll run into is that (at least in my experience) django won't create them in the test environment and you end up running into issues because there is no migration file to create those tables (since they're unmanaged). Django runs the migration files when creating the test environment.
With Pytest you can run with a --nomigrations flag which builds your test database directly off the models (thus creating the tables you need for your unmanaged models).
If you combine Pytest and Factory Boy you should be able to come up with the ability to setup your test data so it works as expected, is repeatable and testable without issue.
I actually approach it like this (slightly hacky, but it works with our complex setup):
On my model:
class Meta(object):
db_table = 'my_custom_table'
managed = getattr(settings, 'UNDER_TEST', False)
I create the UNDER_TEST variable in settings.py like this:
# Create global variable that will tell if our application is under test
UNDER_TEST = (len(sys.argv) > 1 and sys.argv[1] == 'test')
That way - when the application is UNDER_TEST the model is marked as managed (and Pytest will create the appropriate DB table). Then FactoryBoy handles putting all my test data into that table (either in setUp of the test or elsewhere) so I can test against it.
That's my suggestion - others might have something a little more clear or cleaner.

'Relation does not exist' error after transferring to PostgreSQL

I have transfered my project from MySQL to PostgreSQL and tried to drop the column as result of previous issue, because after I removed the problematic column from models.py and saved. error didn't even disappear. Integer error transferring from MySQL to PostgreSQL
Tried both with and without quotes.
ALTER TABLE "UserProfile" DROP COLUMN how_many_new_notifications;
Or:
ALTER TABLE UserProfile DROP COLUMN how_many_new_notifications;
Getting the following:
ERROR: relation "UserProfile" does not exist
Here's a model, if helps:
class UserProfile(models.Model):
user = models.OneToOneField(User)
how_many_new_notifications = models.IntegerField(null=True,default=0)
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
I supposed it might have something to do with mixed-case but I have found no solution through all similar questions.
Yes, Postgresql is a case aware database but django is smart enough to know that. It converts all field and it generally converts the model name to a lower case table name. However the real problem here is that your model name will be prefixed by the app name. generally django table names are like:
<appname>_<modelname>
You can find out what exactly it is by:
from myapp.models import UserProfile
print (UserProfile._meta.db_table)
Obviously this needs to be typed into the django shell, which is invoked by ./manage.py shell the result of this print statement is what you should use in your query.
Client: DataGrip
Database engine: PostgreSQL
For me this worked opening a new console, because apparently from the IDE cache it was not recognizing the table I had created.
Steps to operate with the tables of a database:
Database (Left side panel of the IDE) >
Double Click on PostgreSQL - #localhost >
Double Click on the name of the database >
Right click on public schema >
New > Console
GL

EF6 MySQL changing all table prefixes

I have a mysql db on a server where I've bought some space.
Now I want to add a new mvc application to my website to try out some stuff, without buggering up my existing application.
That puts me in a bit of a problem though as I only have one database available, I could just buy a new one, but I don't want to have to buy a new one every time I want to try stuff out.
So I figured, why not just pre-fix all my tables with some unique value for that application, that way I can keep the stored data separate while still using the same db.
That took me on a journey across countless articles both here on stackoverflow and other places on the web.
After about a day I stumbled upon this nugget
<!-- language: c# -->
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Types().Configure(entity => entity.ToTable("pf_" + entity.ClrType.Name));
base.OnModelCreating(modelBuilder);
}
Which does exactly what I want, as long as you either use a mssql database, or you drop your mysql database and create a new one.
However, the database I've been given is not an mssql database, and dropping it is not an option.
When, with an existing mysql db, I try to run
update-database
I get the following error
Can't find file: '.\mytestdb\dbo#002etestitems.frm' (errno: 2 - No such file or directory)
where "mytestdb" is my local db that I'm testing on, "testitems" is the current/previous tablename, .frm is ofcourse the db format, and I have no idea what this "dbo#002e" is, I tried googling it to no avail.
My stack trace can be found here.
http://pastebin.com/yF2dGkm6
Has anyone been in a similar situation, or has ideas as to how I can make it work? =)
dbo#002e stands for "dbo.", looking at your migration file you should discover rows like this one:
RenameTable(name: "dbo.Table", newName: "pf_Table");
Despite everything it's ok with CreateTable with table names prefixed by "dbo.", RenameTable origin the whole "dbo.Name" to be looked for and so the error comes.
My suggestion is to remove manually the "dbo." on the RenameTable's "name:" parameter.
EDIT:
After fixed the problem editing the migration file the best solution is to add this to the Configuration constructor:
public Configuration()
{
AutomaticMigrationsEnabled = false;
....
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
CodeGenerator = new MySql.Data.Entity.MySqlMigrationCodeGenerator();
....
}
It should work since the .Net Connector version 6.7.4 on.

EntityFramework on MySql changing connection string does not change results data

I'm working with EntityFramework 5.0 and MySql. I have generated model from database, and my application now have to connect on multiple database with same structred data.
So i have to dynamic change connection string based on some info.
I try to change database name even from config section of connection string, and with EntityConnectionStringBuilder, but i had the same result: my new connection is stored correctly, but data returned are of the first database.
From WebConfig:
add name="dbIncassiEntities" connectionString="metadata=res:///DAL.Modelincassi.csdl|res:///DAL.Modelincassi.ssdl|res://*/DAL.Modelincassi.msl;provider=Devart.Data.MySql;provider connection string="user id=root ... database=dbname2"" providerName="System.Data.EntityClient" />
From code:
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Provider = providerName;
entityBuilder.ProviderConnectionString = "user id=...database=dbname2";
entityBuilder.Metadata = #"res://*/DAL.Modelincassi.csdl|res://*/DAL.Modelincassi.ssdl|res://*/DAL.Modelincassi.msl";
var context = new dbIncassiEntities(entityBuilder.ToString());
My constructor:
public dbIncassiEntities(string conn)
: base(conn)
{
}
What am i missing?
UPDATE
I can see that calling a query directly from SqlQuery, results returned are correct,
while using the generated entities i retrieve wrong data.
var test = context.Database.SqlQuery<string>(
"SELECT cognomenome FROM addetto limit 0,1").ToList();
But calling..
var oAddetto = from c in context.addettoes select c;
So my problem is only on the model itsself, and manually changing the generated schema
<EntitySet Name="addetto" EntityType="dbIncassiModel.Store.addetto" store:Type="Tables" Schema="dbname2" />
..i'll get the right information.
My question now is: how can i change in code these informations??
Any help is really appreciated!!
Thanks, David
Ok, i've found a workaround for now.
I simply clear the shema name on the designer, and now i can call the generated entities succesfully. Hope this can help anyone else.
David
While I could not remove the Schema in the designer, I removed it directly in the .edmx file. Do a full text search for Schema="YourSchema" in an XML editor of your choice and remove the entries. After that, changing the connection string is enough.
Downside is, the Visual Studio designer and mapping explorer won't work properly anymore.
This seems to be more of a dotConnect issue rather than MySQL, since the problem also exists for the Oracle adapter:
http://forums.devart.com/viewtopic.php?t=17427

CaseSenstive Table names

hi there i made track star application and everything works fine except for one issue that i face error
CDbCommand failed to execute the SQL statement: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'devnmark_root.AuthAssignment' doesn't exist. The SQL statement executed was: SELECT *
FROM 'AuthAssignment'
WHERE userid=:userid
now this was automatically generated by Yii when i checked for if(Yii::app()->user->checkAccess('createUser',array('project'=>$model)))
18 {
19 $this->menu[] = array('label'=>'Add User To Project','url'=>array('adduser', 'id'=>$model->id));
20 }
then i went to phpmyadmin and executed this query manually
SELECT * FROMAuthAssignmentWHERE userid=4 and there is error which says same that table does not exist.
if i use small case letter for table name then no error.
i executed same query on local wamp 's phpmyadmin same query does not show any error there so this is clear that there is error with my sql .any idea what can i do to solve?
I suggest you hitting up SQL_MODE documentation for setting your final options. http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
For testing you can just do a:
SET sql_mode = '';
Or adjust your command line:
--sql-mode=""
You may try to set the system variable *lower_case_table_names* to 1.
My local application was developed under Windows, howerver production is under Linux and I caused the same problem.
For me it happened because of case sensitivity - table AuthAssignment in database was actually authassignment.
I have found two options to solve it:
rename database table from authassignment to AuthAssignment
or
edit config file component section:
'components'=>array(
...
'user'=>array(...
),
'authManager'=>array(
...
'assignmentTable'=>'authassignment' //THIS LINE SOLVED MY PROBLEM
),
I had the same problem of non-existent authassignment table, I had forgotten running the rights installation which in my case was by following URL i.e.
/index.php/rights/install
and then the setup was like a breeze and self explanatory :)
For me this answer helped the most: original source.
In the authManager in config/main.php you can add lowercased names of the tables like this:
'components'=>array(
'authManager'=>array(
'defaultRoles'=>array('guest'),
'class'=>'RDbAuthManager',
'assignmentTable'=>'authassignment',
'itemTable'=>'authitem',
'rightsTable'=>'rights',
'itemChildTable'=>'authitemchild',
),