13

I have the following mapping:

public class LogEntryMap
{
    public LogEntryMap()
    {
        Map.Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.Context).CustomSqlType("varchar").Length(512);
    }
}

However, using SchemaExport to generate the database in SQL Server 2008, the script generated ignores the length so in effect it ends up being a varchar with length of 1:

create table OV_SAC.dbo.[LogEntry] (
    Id BIGINT IDENTITY NOT NULL,
   Context varchar null,
   primary key (Id)
)

.CustomSqlType("varchar 512") throws an exception. And without defining the CustomSqlType, strings are mapped to nvarchar (which does respect the Length property).

Any suggestions?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Ted
  • 7,122
  • 9
  • 50
  • 76

4 Answers4

23

Use .CustomType("AnsiString") instead of default "String" and NHibernate will use varchar instead of nvarchar.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Szymon Pobiega
  • 3,358
  • 17
  • 18
17

If you wanted all of your strings to be mapped to varchar instead of nvarchar you could consider using a convention:

/// <summary>
/// Ensures that all of our strings are stored as varchar instead of nvarchar.
/// </summary>
public class OurStringPropertyConvention : IPropertyConvention
{
    public void Apply(IPropertyInstance instance)
    {
        if (instance.Property.PropertyType == typeof (string))
            instance.CustomType("AnsiString");
    }
}

You mappings could then go back to a simple mapping:

Map(x => x.Context);

Just make sure you remember to tell Fluent NH to use the convention:

        var configuration = new Configuration();
        configuration.Configure();
        Fluently
            .Configure(configuration)
            .Mappings(m => m.FluentMappings
                .AddFromAssemblyOf<Widget>()
                .Conventions.Add<OurStringPropertyConvention>()
                )
            .BuildSessionFactory();
Jonathan Moffatt
  • 13,309
  • 8
  • 51
  • 49
  • Great!! Now, what if I want ALL my properties as varchar, except one? Can I override the CustomType for that entity in the mapping without being overwritten by the convention? – Gerardo Grignoli Oct 27 '17 at 13:16
  • @GerardoGrignoli: yes you can. Conventions only set the defaults. If you use ansi-string convention, and then make a specific column mapping to have i.e. `.CustomType`, it will work just like you'd expect. – quetzalcoatl Nov 06 '17 at 10:35
8

Doh.

Map(x => x.Context).CustomSqlType("varchar (512)");

create table OV_SAC.dbo.[LogEntry] (
    Id BIGINT IDENTITY NOT NULL,
   Context varchar (512) null,
   primary key (Id)
)
Ted
  • 7,122
  • 9
  • 50
  • 76
0

We found using the "CustomType("AnsiString")" option does prevent it from using the nvarchar, however, it sets the field length of 8000 for a column that is specified as varchar(30). The 8000 varchar is much faster than 4000 nvarchar, but it is still causing huge problems with sql server overhead.

Joel WZ
  • 100
  • 8