Create a column with varchar(max) rather than varchar(8000)

泪湿孤枕 提交于 2019-12-05 01:38:54

Worked around the issue by doing the following

 if (!db.TableExists(typeof(Entity).Name))
 {
   db.CreateTableIfNotExists<Entity>();
   db.ExecuteSql("ALTER TABLE Entity ALTER COLUMN Column VARCHAR(MAX)");
 }

Decorate your domain model with System.ComponentModel.DataAnnotations.StringLengthAttribute

such as

[StringLengthAttribute(8001)]
public string Markdown { get;set; }

or

[StringLength(Int32.MaxValue)]
public string Markdown { get;set; }

using any length greater than 8000 to exceed to maximum length of Sql Server varchar/nvarchar column types that required the MAX declaration.

Use a custom dialect provider the understands the MAX declaration.

public class MaxSqlProvider : SqlServerOrmLiteDialectProvider
{
  public new static readonly MaxSqlProvider Instance = new MaxSqlProvider ();

  public override string GetColumnDefinition(string fieldName, Type fieldType, 
            bool isPrimaryKey, bool autoIncrement, bool isNullable, 
            int? fieldLength, int? scale, string defaultValue)
  {
     var fieldDefinition = base.GetColumnDefinition(fieldName, fieldType,
                                    isPrimaryKey, autoIncrement, isNullable, 
                                    fieldLength, scale, defaultValue);

     if (fieldType == typeof (string) && fieldLength > 8000)
     {
       var orig = string.Format(StringLengthColumnDefinitionFormat, fieldLength);
       var max = string.Format(StringLengthColumnDefinitionFormat, "MAX");

       fieldDefinition = fieldDefinition.Replace(orig, max);
     }

     return fieldDefinition;
  }
}

Use the provider when you construct the database factory

var dbFactory = new OrmLiteConnectionFactory(conStr, MaxSqlProvider.Instance);

Note this illustration is specifically targeting SqlServer but it would be relevant for other data providers with minor alterations after inheriting from the desired provider.

It appears that ServiceStack has addressed this with a feature to further customize the creation type of fields, see: https://github.com/ServiceStack/ServiceStack.OrmLite#custom-field-declarations

or as detailed at that link:

The [CustomField] attribute can be used for specifying custom field declarations in the generated Create table DDL statements, e.g.:

public class PocoTable
{
    public int Id { get; set; }

    [CustomField("CHAR(20)")]
    public string CharColumn { get; set; }

    [CustomField("DECIMAL(18,4)")]
    public decimal? DecimalColumn { get; set; }
}

Where

db.CreateTable<PocoTable>(); 

Generates and executes the following SQL:

CREATE TABLE "PocoTable" 
(
  "Id" INTEGER PRIMARY KEY, 
  "CharColumn" CHAR(20) NULL, 
  "DecimalColumn" DECIMAL(18,4) NULL 
);  

Again however, as per my comment o one of the previous answers, I am guessing that this is probably db-specific, sorry, I don't have easy access to several db servers to test.

The column definition of each type can be controlled using OrmLite's Type Converters where the default SqlServerStringConverters will use VARCHAR(MAX) for properties attributed with [StringLength(StringLengthAttribute.MaxText)], e.g:

public class PocoTable
{
    public int Id { get; set; }

    [StringLength(StringLengthAttribute.MaxText)]
    public string MaxText { get; set; }

    [StringLength(256)]
    public string SmallText { get; set; }
}

Using StringLengthAttribute.MaxText (or its alias int.MaxValue) will automatically use the most appropriate datatype for storing large strings in each RDBMS.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!