EF 4.1 RTW Change to Default MaxLength in Code First

 


The information in this post is out of date.

Visit msdn.com/data/ef for the latest information on current and past releases of EF.


 

We recently announced the release of ADO.NET Entity Framework 4.1 Release Candidate which included the first go-live release of Code First. The final Release to Web (RTW) is planned to be released approximately a month after the Release Candidate (RC) was published. Between RC and RTW we are not adding any new features and are focusing on fixing any bugs or issues reported by folks using the RC.

 

The Issue

One issue that has been raised by a number of folks is the side effects of changing the default maximum length of strings and arrays from 4000 in CTP5 to 128 in RC.

In particular this causes issues when mapping to an existing database with Code First because the new validation feature will ensure that all string and array data is shorter than 128 before trying to save. This results in a DbEntityValidationException stating:

 “Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.”

Inspecting the validation result states that:

"The field <property name>must be a string or array type with a maximum length of '128'."

Besides the inconvenience of having to explicitly specify the max length of most columns when mapping to an existing database we are hearing that 128 is just too short for a default and we need to chose something more appropriate.

 

The RC Workaround

There are two ways to resolve this issue in the RC release:

  • Disable validation by setting ‘DbContext.Configuration.ValidateOnSaveEnabled’ to ‘false’
    By doing this Code First will not attempt to verify the length of string/array data and even though it thinks the max length is 128 it will leave it up to the database to decide if it can store that data or not.
  • Configure the correct string length for each string property using the MaxLength data annotation or the HasMaxLength method in the fluent API.
    This is the most technically correct solution, but we realize that configuring a length for every string/array property in your model is often going to result in a lot of repetitive configuration.

 

The RTW Change

Based on this feedback we are proposing to change the default length of non-key properties to be ‘Max’ (this equates to varchar(max) and nvarchar(max) when running against MS SQL Server). Key properties and TPH discriminator columns will remain with a default max length of 128.

SQL Compact does not support ‘Max’ columns, when running against SQL Compact an additional Code First convention will set a default max length of 4000.

Introducing this change will cause a model generated by EF 4.1 RTW to be different from one generated by EF 4.1 RC. This means that in scenarios where Code First is generating the database you will need to re-create the database with the new column types. This only affects scenarios where the default length is used, if you have explicitly configured a maximum length then Code First will continue to honor it. If your model changes as a result of the new max length default you would receive the following exception when running the application:

“The model backing the <derived context type name> context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the RecreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data."

 

As always, we thank you for your continued feedback that is helping us shape this exciting release.

Rowan Miller
Program Manager
ADO.NET Entity Framework

Comments

  • Anonymous
    March 31, 2011
    That solution sounds fine to me.

  • Anonymous
    March 31, 2011
    Good news. From this post I understand you are in the fase of fixing bugs. Is it possible to share some news on the bugfixes regarding multilevel TPH inheritance when using abstract classes?  

  • Anonymous
    April 01, 2011
    What's the best way to send feedback?  I have a scenario that doesn't work in EF, and I'd love to send a description to someone on the product team, but it seems a bit long for a blog comment.

  • Anonymous
    April 01, 2011
    Thanks for the info. That sounds like the best course of action to me. I did not like the arbitrary 128 character default but will probably try to set a default.

  • Anonymous
    April 03, 2011
    One issue that I see with changing it to MAX is that you can't index those columns. It seems like you should set it to the max value that is allowed for an indexable column. Also, I'm not sure what the performance implications of having it set to MAX would be.

  • Anonymous
    April 05, 2011
    What about third-party providers? For example, MySql doesn't have a varchar(MAX) type, but presumably won't use the SQL Compact convention. Since you've removed the ability to add custom conventions for code-first, how will EF4.1 handle this?

  • Anonymous
    April 10, 2011
    After update EF4.1,Can not write data in database。why? -----------------------------------------------------------------------------------------------------------------------------from china 如题:升级到EF4.1 RC 后 seed()方法里面的数据无法写入到 数据库中 我的测试项目升级到EF4.1 RC 后 seed()方法里面的数据无法写入到 数据库中。大师们有没有类似的问题啊: DBInitializer代码----: 1 public class DBInitializer : DropCreateDatabaseIfModelChanges<ConferenceMSEntitiesContext> 2     { 3         protected override void Seed(ConferenceMSEntitiesContext context) 4         { 5             var de = new List<Department> { 6                 new Department{ 7                     Name="小庙", 8                     DepartmentTypeID=1 9                 }, 10                 new Department{ 11                     Name="经济局", 12                     DepartmentTypeID=3 13                 }, 14   15                 new Department{ 16                     Name="发改局", 17                     DepartmentTypeID=3, 18             19                 } 20 21             }; 22 23   24 25             de.ForEach(d => context.Departments.Add(d)); 26             27 28 29   30             31     32         } 33           34     } 35 } 以上代码最后不论是否添加     base.Seed(context); 和  context.SaveChanges(); 这两行代码,都无法把数据写进数据库。 Application_Start----------------- 1  protected void Application_Start() 2         { 3           4             System.Data.Entity.Database.SetInitializer<ConferenceMSEntitiesContext>(new DBInitializer()); 5         6             AreaRegistration.RegisterAllAreas(); 7 8             RegisterGlobalFilters(GlobalFilters.Filters); 9             RegisterRoutes(RouteTable.Routes); 10         }

  • Anonymous
    April 10, 2011
    Hi, Today, I realised that when I issued the command Submitchanges(), the EF code first wont just update the table it's supposed to be, but also does a cascade update across the foreign key tables too.

  1. Why does it do that?
  2. Is there any way to prevent that? cause it's causing Optimistic Concurrency Exception in my application. Thanks, Sam
  • Anonymous
    April 21, 2011
    Hi, I think I have a bug for you in respect to the Image data type of SQL CE and Entity Framework 4.1. Take a look at the question I posted at StackOverflow: stackoverflow.com/.../114029 I solved the problem using the 1st approach described in this post. Thanks, Leniel

  • Anonymous
    April 25, 2011
    As Jon Miller said, varchar(max) columns cannot be indexed. There are also known performance issues when querying varchar(max) columns: there is additional overhead both at the server level and at the TDS protocol level (used by the SQL native client). Using a constant number (e.g. varchar(4000)) would be better.