Вопрос по fluent-nhibernate, nhibernate-mapping, nhibernate, varbinary – Как получить свободный nhibernate для создания поля varbinary (max) на сервере SQL

14

Как я могу свободно использовать nhibernate для создания поля varbinary в таблице sql server 2005, в которой используется размер поля varbinary (max)? В настоящий момент я всегда получаю значение по умолчанию varbinary (8000), которое недостаточно велико, поскольку я собираюсь хранить файлы изображений.

Я пытался использовать CAstle.ActiveRecord, но пока не добился успеха.

 [ActiveRecord]
 public class MyFile : Entity
{
    public virtual string FileName { get; set; }
    public virtual string FileType { get; set; }
    public virtual int FileVersion { get; set; }
    public virtual int FileLength { get; set; }

    [Property(ColumnType = "BinaryBlob", SqlType = "VARBINARY(MAX)")]
    public virtual byte[] FileData { get; set; }   
}

Уже несколько часов не могу найти решение, так что спасибо заранее

Кч

Ваш Ответ

6   ответов
1

в Fluent NHibernate нет такой вещи, как «max», однако, если вы установите разрешенную длину столбца в действительно большое значение, она должна работать нормально. Вы можете проверить MSDN, какое значение max max означает для каждого типа данных в SQL Server, хотя в других это может означать совсем другое число.

Я использовал отражатель и нашел это:

public MsSql2005Dialect()
{
    base.RegisterColumnType(DbType.String, 0x3fffffff, "NVARCHAR(MAX)");
    base.RegisterColumnType(DbType.AnsiString, 0x7fffffff, "VARCHAR(MAX)");
    base.RegisterColumnType(DbType.Binary, 0x7fffffff, "VARBINARY(MAX)");
}

Итак, кажется, что NHibernate создает max по умолчанию? Тем не менее, Fluent не делает. (Хотя я не знаю почему.)

С помощью функции автоматического сопоставления вы можете использовать соглашения для достижения этой цели.

Пример:

var cfg = new Configuration();

var persistenceModel = new AutoPersistenceModel();
persistenceModel.Conventions.Add(
    new PropertyConvention(),
    new ReferenceConvention(),
    new HasManyConvention(),
    ConventionBuilder.Property.Always(delegate(IPropertyInstance instance)
    {
        if (instance.Property.PropertyType == typeof(string))
            instance.Length(16000);
        else if (instance.Property.PropertyType == typeof(byte[]))
            instance.Length(30000000);
    }));
persistenceModel.AddTypeSource(new AssemblyTypeSource(Assembly.GetExecutingAssembly()));
persistenceModel.Where(t => t.Namespace.EndsWith("Entities"));

cfg.AddAutoMappings(persistenceModel);
return cfg.BuildSessionFactory();

Для меня этого достаточно, но вы всегда можете использовать большие числа.

Я полагаю, что если вы не используете автоматическое копирование, решение Дана Фитча - это то, что вам нужно.

2

В картировании используйте:

Map(x => x.FileData).CustomSqlType("VARBINARY(MAX)");

0

я (досадно) поместил файл карты в основной проект, а не в проект данных.

Я все еще не могу заставить его работать с файлом карты, но вместо этого я написал XML-файл, записав его длину - спасибо за это, Дэн

 <property name="FileName"/>
 <property name="FileType"/>
 <property name="VersionNo"/>
 <property name="FileLength"/>
 <property name="FileData" length="2147483647"/>
10

почему ваш пример ActiveRecord не работает, но там вы можете попробовать установить длину столбца.

С Fluent NHibernate, вы должны быть в состоянии сделать

Map(x => x.FileData)
    .WithLengthOf(2147483647)
5

когда мои BLOB-записи усекались до 8000 байт. Следующий синтаксис окончательно решил проблему:

Map(x => x.Bytes)
  .CustomSqlType("VARBINARY (MAX) FILESTREAM")
  .Length(2147483647)
  .Not.Nullable();
int.MaxValue может быть, лучший способ выразить магическое число. Как в.Length(int.MaxValue)
2

public class MyFileMapOverride : IAutoMappingOverride<MyFile>
{
    public void Override( AutoMapping<MyFile> mapping )
    {
        mapping.Map( x => x.FileData ).Length( int.MaxValue );
    }
}

Поскольку вы используете Castle, вы можете указать ему подключить NHibernate с вашими сопоставлениями в NHibernateInstaller:

public void Install( IWindsorContainer container, IConfigurationStore store )
{
    container.Register( Component.For<ISessionFactory>()
                                 .UsingFactoryMethod( k => BuildSessionFactory() )
                                 .Named( "MySessionFactory" ) );

    // Do other stuff...
}

private ISessionFactory BuildSessionFactory()
{
    var mappings = AutoMap.AssemblyOf<MyFile>()
                          .IgnoreBase( typeof(Entity) )
                          .UseOverridesFromAssemblyOf<MyFileMapOverride>();

    var configuration = ConfigurationUtility
        .CreateConfiguration<WebSessionContext, DefaultProxyFactoryFactory>(
            "MyDbConnection",
            ConfigurationUtility.ForMsSql,
            mappings,
            NHibernateConfiguration.GetConfigurationPath() );

    return configuration.BuildSessionFactory();
}

Похожие вопросы