Почему сгенерированный SQL объявляет параметры длиной 8000 или 4000 вместо длины, указанной в отображении?

Отображение длины nibernate varchar и nchar игнорируется, когда поле varchar используется с соглашением NHibernate

Вместо сопоставления varchar со значениями в сопоставлении, которые они сопоставляют с varchar(8000) и nchar(4000), это приводит к тому, что обновление занимает очень много времени, и впоследствии блокирует другие обновления.

Мы используем:

Microsoft SQL Server 2016

FluentNHibernate Версия 1.3.0.0

NHibernate версия 3.3.1.4000

public UserMap()
{
    Table("User")
    Id(x=>x.Id, "User_ID")
    Map(x=>x.User_refNo, "User_refNo").Length(255).Nullable();
    Map(x=>x.Name,"Name").Length(100).Nullable();
    Map(x=>x.Gender,"Sex").Nullable();
}

Сгенерированное обновление SQL

@p0 AnsiString(8000),
@p1 AnsiString(8000),
@p2 nchar(4000),
@p3 int;
UPDATE dbo.User SET
 User_refNo = @p0,
 Name = @p1,
 Sex = @p2 WHERE User_ID = @p3

Чтобы добавить это как-то связано с типом varchar и PropertyConventions

public void Apply(IPropertyInstance instance)
{
    if (instance.Property.PropertyType == typeof(string))
        instance.CustomType("AnsiString");
}

Если я изменяю соглашение следующим образом, отображение улучшается:

public void Apply(IPropertyInstance instance)
{
   if (instance.Type == typeof(string))
   {
        instance.CustomSqlType($"varchar ({2000})");
   }
}

Теперь сгенерированный SQL выглядит так:

@p0 String(4000),
@p1 String(4000),
@p2 String(4000),
@p3 int;
UPDATE dbo.User SET
 User_refNo = @p0,
 Name = @p1,
 Sex = @p2 WHERE User_ID = @p3

Однако нам требуется тип AnsiString.

1 ответ

Возможный дубликат: NHibernate игнорирует атрибут длины

и более ранний вариант с тем же ответом: свободное сопоставление NHibernate со столбцом идентификатора CHAR(10) SQL Server

В основном, NH игнорирует длину в запросах и параметрах и использует значение по умолчанию. Таким образом, String всегда nvarchar(4000) и AnsiString varchar(8000).

Моя похожая проблема - сопоставление столбца Gender с char(1) и NH с запросом, подобным следующему:

return GetNamedQuery("xxxxxxx")
    .SetAnsiString("name", name)
    //.SetParameter("gender", gender, NHibernateUtil.AnsiChar) //char version
    .SetCharacter("gender", gender) //nchar version

Создает SQL, такой как этот:

exec sp_executesql N'select ... where ... Name=@p3 and ... Gender=@p5',
N'... @p3 varchar(8000),... @p5 char(8000)',... @p3='NAME GOES HERE'...,
@p5='M               [padding with 7999 spaces here ]                        ',@p6=0

Мне кажется неправильным, а также генерирует дополнительный платный сетевой трафик между экземплярами в облачной среде. План SQL-запросов не кажется затронутым.

Ошибка NH, все еще открытая: https://nhibernate.jira.com/browse/NH-3403

Другие вопросы по тегам