We are currently developing a product using Code First Entity Framework and Mysql. The development database is hosted in a Windows environement while the production mysql is on
with EF6 :
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Types().Configure(entity => entity.ToTable(entity.ClrType.Name.ToLower()));
}
Entity framework creates a query like this:
Select * FROM mydatabase.Industry; Notice the capitalized letter. This works fine on mysql in Windows, but on Linux I get this error:
Table 'mydatabase.Industry' doesn't exist Any Ideas?
This has nothing to do with entity framework itselfs.
It is a variation of the classic different default configuration on two different OS'es problem.
The solution may not be necessary anymore, but here's the reason for your problem:
MySQL stores tables as files.
And MySQL was originally developped on Linux, where the filenames and therefor the tablenames were case-sensitive (because most Linux filesystems are case-sensitive).
Then MySQL was ported to Windows, where the filesystem is case-insensitive.
On windows, the file-system is case-insensitive, and hence cannot distinguish lower&upper case files.
To resolve the resulting problems, there needed to be added the option to ignore the case of the table names.
So the identifier case-senstivity configuration variable "lower_case_table_names" was created, with which one can switch those settings.
Further information on the possible values [0, 1, 2] here:
http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html
On Windows, you can configure it in the my.ini file, found in or around:
C:\Program Files\MySQL\MySQL Server X.Y
, depending on which version you are running. If you don't find the setting, you can just add it to the end of the my.ini file.
On Linux, this config file is usually located in /etc/my.cnf or /etc/mysql/my.cnf but that may vary on the various Linux-dristributions and distribution versions.
So the default for this value is
on Linux: Case-Senstivie
on Windows: Case-Insensitive
Therefore, entity-framework generated SQL which was generated from a model with wrong casing works on Windows, but not on Linux.
All you need to do is to change the value of lower_case_table_names on Linux to 1 in the my.cnf file so that it is case-insensitive as well.
Note that while you could also make MySQL on Windows case-sensitive, this is not a good idea.
Then, remember to restart the MySQL service/mysqld before you test whether or not it works.
In all cases, always remember to check whether it works on Linux as well, as the behaviour of MySQL is not always identical on those two systems.
The reason for the different defaults is that on Linux you have a higher performance when you are in case-sensitive mode, because then you don't always have to lowercase names. On Windows on the other hand, having a case-insensitive configuration is better, because you can't have two files with the same name that only differ in casing in the same folder. This would lead to malfunctions. So the default is case-insensitive on Windows.
Incidentially, this is why the performance of MySQL on Linux is better than the performance on Windows (amongst other things, like better scheduling and faster IO/filesystem on Linux)
Note that you can also change the case-sensitity of queries (string comparison) by doing
CREATE DATABASE test_database CHARACTER SET utf8 COLLATE utf8_general_cs;
or
CREATE DATABASE test_database CHARACTER SET utf8 COLLATE utf8_general_ci;
respectively
And you can also set case-sensitivity on a single table, like this
DROP TABLE IF EXISTS single_test_table;
CREATE TABLE single_test_table(
single_test_id int unsigned NOT NULL auto_increment,
...
PRIMARY KEY PK_single_test_id (single_test_id ),
...
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_general_cs;
Entity Framework will use the same name (capitalization, etc) as is declared for the object. So, for example, if you declare a model object as:
public class Industry
{
public int IndustryID { get; set; }
}
Entity Framework will look for a table of Industry with a column of IndustryID.
You can change this by adding annotations to your models. Do the following:
[Table("industry")]
public class Industry
{
public int IndustryID { get; set; }
}
By doing this, your objects will still use the appropriate .NET naming scheme, but it will match your corresponding database. You can also change the name of the colunns using ColumnAttribute.
Alternatively, you could change the table names in MySQL.
Here is my answer taken from the comments:
usr: Why don't you change the configured table name to lowercase? The SQL table name and the entity name are independently configurable.
AFrieze: Do you mean change the entity name to lowercase? So instead of a C# class "Industry" I would have a class "industry"?
usr: No the two are different. You can have table name xyz mapped to entity Abc. – usr just now edit