EF 6 automatic migration column name uppercase rename not detected - entity-framework

We are using EF6 code first approach and we have automatic migrations enabled (we are at the beginning of the project).
Database.SetInitializer(new MigrateDatabaseToLatestVersion<OurDbContext, Configuration>());
And in the Configuration class we have the following enabled in order for the DB to be updated automatically during each application start:
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
The DB column names are explicitly mapped like this (with "HasColumnName") because we want to have full control over the column names:
modelBuilder.Entity<User>().Property(u => u.Gender).IsRequired().HasColumnName("Gender");
I've just noticed today that when I changed the name of the mapped column to begin with a lowercase ex:
modelBuilder.Entity<User>().Property(u => u.Gender).IsRequired().HasColumnName("gender");
... the automatic migration does not detect this as a change to the DB and does nothing i.e. the DB column name stays the same ("Gender" with an uppercase g).
It was only after I changed the column name to another word ex:
modelBuilder.Entity<User>().Property(u => u.Gender).IsRequired().HasColumnName("genders");
...that caused the automatic migrations to actually change the column name in the DB, which indicates that somehow the check for column name is done in a case insensitive way.
Does anyone know if this is by design, or is this a bug in EF?
Additionally is there a way to force the automatic migrations to perform case sensitive column name checks?
Thanks in advance

Case sensitivity does not make much difference to DB, so I believe this is intentional.
If you don't like lowercase column name, just work around this:
Rename the column from "gender" to something like "genders". Add migration
Rename column back to "Gender". Add migration
Alternatively, you can manually edit generated migration code

Related

How to make Entity Framework Add-Migration case sensitive

I changed an entity property from name to Name and the Add-Migration command didn't add the change to the migration file. Is it possible to set the command to pick up on changes with case sensitivity? Or do I have to drop the columns and add them again?
Rename the column from "testname" to something like "testnames". Add migration
Rename column back to "TestName". Add migration
Alternatively, you can manually edit generated migration code

Why does Entity Framework insist on renaming columns?

Step 1: import code first from existing database. Existing database has a table with the same name as column.
Step 2: in this scenario, Entity Framework sticks a "1" in front of column name in code.
Step 3: when I try to rename it "by getting rid of 1 in front", I get error
member names cannot be the same as their enclosing type
Why is this limitation on EF and is there a solution that doesn't ruin the database in future migrations (by having that column renamed)?
Being forced to use Column1 just seems really terrible and arbitrary.
Thanks.
As pointed out by #shf301 you cant have a property named the same as the class its in, this is a .NET restriction.
However you can name your column anything else and then tell EF to point to your specific column in the database
eg:
[Column("MyColumn")] // "MyColumn" will be what EF expects in the db
public int FlyingMonkies {get;set;}

Can you pass extra parameters in addition to the primary key to the stored proc for Entity Framework 6 deletes?

I'm using Entity Framework 6.1 and we have mapped our CUD stored procs to our entities.
Everything works great for creates and updates. However, for deletes, I would like to pass the modified by username to the delete stored proc so that we can log it in the audit tables.
I tried adding these extra parameters to the model builder when I map the stored procs:
private void MapStoredProcNamesWithExtraDeleteParams<T>(DbModelBuilder modelBuilder) where T : BaseAuditableObject
{
var tableName = typeof(T).GetCustomAttributes(false).OfType<TableAttribute>().First();
modelBuilder.Entity<T>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName(string.Format("{0}Update", tableName.Name)))
.Delete(d => d.HasName(string.Format("{0}Delete", tableName.Name))
.Parameter(x => x.ModifiedBy, "ModifiedBy")
.Parameter(x => x.ModifiedBy, "ModifiedDate")
.Parameter(x => x.ModifiedBy, "ModifiedByProgramName")
)
.Insert(i => i.HasName(string.Format("{0}Insert", tableName.Name))));
}
However, that fails because it says there is no ModifiedBy field on the Delete function.
Is there some way to do this or do I have to first update the modified by, save changes, then delete the object, and save changes again?
Found a work-around for the issue that allowed me to do what I wanted, albeit with some extra work.
To get around this we added the ConcurrencyCheck attribute to all the extra properties that we wanted to pass to the delete stored procedure. Next we had to add those properties plus _Original to all the update and delete stored procedures (even though we only used them in the delete ones).
So if your property name was ModifiedBy you would add a parameter to your update and delete stored procs called #ModifiedBy_Original.
Once we did that we could get the data we wanted in the delete stored procs as desired.
The person that last modified the record is not necessarily the person that deletes the record. Adding a concurrency check on ModifiedBy will indeed pass the modifiedby column of the record to the deleted stored proc's parameter named #ModifiedBy_Original but this is not what you need in this case.
I am saying this because we are facing the same issue and are trying to figure out how we can pass the name of the person that deletes a record to the delete stored proc.

EF code-first migration: SqlCeException altering NTEXT column

My application uses Entity Framework 5.0 code-first on top of a Sql CE database. Until now, we have used Automatic Migrations to manage entity mapping changes. However, I now have a change for which I need to create a custom migration to ensure no data is lost during the update. I made my changes to the entities, and used the Add-Migration command which generated Up() and Down() methods for me. I customized the Up() method to insert my custom sql to preserve the data, and tested my application.
When I run the application, I received the error:
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
Ok, I don't understand this because all of my changes are detailed in the Up() method that got executed.
So I turn Automatic Migrations back on just to see what happens. Now I receive this error:
"Cannot alter column of type NTEXT or IMAGE [ Column Name = LastName ]"
This error comes from a table/entity that hasn't even been touched with my changes. The existing database has this string mapped to nvarchar(4000). If I examine the DB after I receive this exception, I observe that the columns have been changed to ntext. What is EF doing? Why is it touching tables that haven't been changed? How can I get more information on what is going on here?
Update:
As a workaround, I attempted to mark each and every string type in my entities with a data annotation as such:
[Column(TypeName = "ntext")]
public virtual string LastName
{
get;
set;
}
Now all of my strings are using ntext in the database. This leads to further exceptions when queries are performed:
The ntext and image data types cannot be used in WHERE, HAVING, GROUP BY, ON, or IN clauses, except when these data types are used with the LIKE or IS NULL predicates.
So, to summarize:
Turning off automatic migrations causes EF to detect phantom changes and throw exceptions
Turning on automatic migration in conjunction with a custom migration causes all existing strings to be mapped to ntext
strings mapped to ntext cannot be queried, effectively making them useless in my application
For me, a modification of an Up method worked out.
SerialNumber = c.String(maxLength: 99)
was applied instead of
SerialNumber = c.String()
i had the same issue and i fixed by editing the table column data type manually by opening SQl Server Compact/SQlite Toolbox explorer windows, and then expend the database name, then expend the table you want to edit and right click the column you want to edit, and click drop script, then run the scrip and the column will be dropped from the table, then right click the table and click add column and from here you can choose what data type you want and add the new column that way. I hope this helps some one.

How to affect the column order with Entity Framework Code First Migrations

I'm using Entity Framework 4.3 Code First and trying out the Migrations feature.
If I add a new property to my class and then run Add-Migration from the package manager console window I get something like this:
public override void Up()
{
AddColumn("Products", "Discontinued", c => c.Boolean(nullable: false));
}
I would like to be able to affect the order of the column as I don't want it to just be appended to the table but rather placed at a specific index. I thought I might be able to add it to my modelBuilder configuration, something like:
Property(p => p.Discontinued).HasColumnOrder(2);
but running Update-database does not appear to use it. Can this be done as a migration?
This is just a matter of missing functionality. SQL by itself does not rely on any implicit order of columns (with some exceptions: ORDER BY , ...).
Neither SQL Server nor ORACLE do have a direct SQL DDL command (aka ALTER TABLE...) to move a column around.
Therefore there's no possibility to change the order without high effort (recreate the table). See for example
How To change the column order of An Existing Table in SQL Server 2008
SQL SERVER – Change Order of Column In Database Tables
https://dba.stackexchange.com/questions/61978/how-to-change-the-column-order