Pergunta

Sempre que você define um valor de string no Nibernate Fluent It Alwasy Define o db vales para nvarchar (255), preciso armazenar bastante string longa, baseada em entradas do usuário e 255 é impraticável.

Apenas para adicionar isso, é um problema com o AutomApper, pois estou usando o Fluent Nibernate para criar o banco de dados.

Foi útil?

Solução

Adicionar esta convenção definirá o comprimento padrão para propriedades da string como 10000. Como outros observaram, esta será uma coluna Nvarchar (Max).

public class StringColumnLengthConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Type == typeof(string)).Expect(x => x.Length == 0);
    }
    public void Apply(IPropertyInstance instance)
    {
        instance.Length(10000);
    }
}

As convenções podem ser adicionadas a uma configuração de automap como esta:

Fluently.Configure()
    .Mappings( m =>
        m.AutoMappings.Add( AutoMap.AssemblyOf<Foo>()
        .Conventions.Add<StringColumnLengthConvention >()))

Para mais informações, veja Convenções no fluente Wiki Nibernate.

Outras dicas

Definir o comprimento para qualquer coisa acima de 4001 gerará um nvarchar (máx) ...

.WithLengthOf(10000);

Veja aqui para mais detalhes ...

http://serialseb.blogspot.com/2009/01/fluent-nhibernate-and-nvarcharmax.html

Com o Fluent Nhibernate Automapper, percebe-se rapidamente que o comportamento pronta para a caixa para colunas VARCHAR é menor que o ideal. Primeiro, você descobre que todas as propriedades da String foram exportadas como Varchar (255) e precisa fazer uma coluna para ser Varchar (Max). Mas, idealmente, você não precisaria fazer de todas as cordas um Varchar (Max), certo? Então, você desce aquele caminho bem trilhado de encontrar a melhor maneira de exercer controle sobre o processo sem romper com os vários padrões elegantes em jogo ...

Se você deseja ter as colunas Varchar resultantes do banco de dados especificadas em diferentes comprimentos, procure as classes de convenções para que isso aconteça. Você pode tentar criar condições específicas de nome ou geralmente usar algum padrão de nomenclatura que você detectou dentro da sua classe de convenção.

Nem é o ideal. Sobrecarregar um nome com o objetivo de indicar uma especificação pretendida em outra parte do código é infeliz- seu nome deve ser apenas um nome. Nem você deve modificar o código da convenção sempre que precisar adicionar ou modificar uma propriedade de classe limitada. Então, como você pode escrever uma aula de convenção que fornece controle e fornece esse controle de uma maneira simples e elegante?

Seria doce se você pudesse apenas decorar Sua propriedade como eu fiz para a propriedade do corpo aqui:

using System; 
using MyDomain.DBDecorations;

namespace MyDomain.Entities {
    [Serializable]
    public class Message
    {
        public virtual string MessageId { get; set; }

        [StringLength(4000)] public virtual string Body { get; set; }
    }
}

Se isso pudesse funcionar, teríamos o controle de cada sequência de forma independente e poderíamos especificá -la diretamente em nossa entidade.

Antes de iniciar um turbilhão sobre a separação do banco de dados do aplicativo, deixe -me ressaltar que isso não é especificamente uma diretiva de banco de dados (fiz questão de não chamar o atributo de 'varchar'). Eu prefiro caracterizar isso como um aumento do sistema.string e, no meu próprio universo, estou feliz com isso. Resumindo, quero uma conveniência!

Para fazer isso, precisamos definir a decoração que queremos usar:

using System;
namespace MyDomain.DBDecorations
{

    [AttributeUsage(AttributeTargets.Property)]
    public class StringLength : System.Attribute
    {
        public int Length = 0;
        public StringLength(int taggedStrLength)
        {
            Length = taggedStrLength;
        }
    }
}

Por fim, precisamos usar uma convenção de comprimento de sequência para usar a decoração de propriedades da entidade. Essa parte pode não parecer bonita, mas faz o trabalho, e a boa notícia é que você não terá que olhar novamente!

StringColumnLengthConvention.cs:

using System.Reflection;
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.AcceptanceCriteria;
using FluentNHibernate.Conventions.Inspections;
using FluentNHibernate.Conventions.Instances;

namespace MyMappings
{
    public class StringColumnLengthConvention : IPropertyConvention, IPropertyConventionAcceptance
    {
        public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria) { criteria.Expect(x => x.Type == typeof(string)).Expect(x => x.Length == 0); }
        public void Apply(IPropertyInstance instance)
        {
            int leng = 255;

            MemberInfo[] myMemberInfos = ((PropertyInstance)(instance)).EntityType.GetMember(instance.Name);
            if (myMemberInfos.Length > 0)
            {
                object[] myCustomAttrs = myMemberInfos[0].GetCustomAttributes(false);
                if (myCustomAttrs.Length > 0)
                {
                    if (myCustomAttrs[0] is MyDomain.DBDecorations.StringLength)
                    {
                        leng = ((MyDomain.DBDecorations.StringLength)(myCustomAttrs[0])).Length;
                    }
                }
            }
            instance.Length(leng);
        }
    }
}

Adicione esta convenção à sua configuração de automappaço e lá você está- sempre que quiser um comprimento específico para resultar durante o ExportSchema, agora você pode simplesmente decorar a propriedade String- e apenas essa propriedade- direita em sua entidade!

Uma das maneiras consistentes que encontrei é:

Map(x => x.LongText, "LongText").CustomType<VarcharMax>().Nullable();

em que o varcarmax e as classes são

public class VarcharMax : BaseImmutableUserType<String>
{
    public override object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        return  (string)NHibernateUtil.String.NullSafeGet(rs, names[0]);
    }
    public override void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        //Change the size of the parameter
        ((IDbDataParameter)cmd.Parameters[index]).Size = int.MaxValue;
        NHibernateUtil.String.NullSafeSet(cmd, value, index);
    }
    public override SqlType[] SqlTypes
    {
        get { return new[] { new SqlType(DbType.String) }; }
    }
}

public abstract class BaseImmutableUserType<T> : NHibernate.UserTypes.IUserType
{
    public abstract object NullSafeGet(IDataReader rs, string[] names, object owner);
    public abstract void NullSafeSet(IDbCommand cmd, object value, int index);
    public abstract SqlType[] SqlTypes { get; }

    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y))
        {
            return true;
        }
        if (x == null || y == null)
        {
            return false;
        }

        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    public Type ReturnedType
    {
        get { return typeof(T); }
    }

    public bool IsMutable
    {
        get { return false; }
    }
}

Olá, me deparei com essa pergunta, com o mesmo problema. Eu tenho um pouco mais seguro maneira de fazer isso, pois não quero que todos os campos de string tenham 10000 chars por padrão.

Em primeiro lugar, registro o Nibernato fluente com algumas substituições

...//snip
....Mappings(m => m.AutoMappings.Add(
                    AutoMap.AssemblyOf<Account>()
                     //Use my mapping overrides here 
                    .UseOverridesFromAssemblyOf<MyMappingOverride>()
                    .Conventions.Add(new MyConventions()).IgnoreBase<Entity>
                ))

Minha aula de substituição de mapeamento se parece com a seguinte:

public class MyMappingOverride : IAutoMappingOverride<MyClass> {
       public void Override(AutoMapping<MyClass> mapping) {
           mapping.Map(x => x.LongName).Length(765);
       }
}

Isso é necessário apenas para pequenos subconjuntos de entidades com valores longos de texto. Talvez alguns mais achem isso útil?

da minha perspectiva, tento usar a Abordagem de não-código primeiro.Perguntando "O que podemos fazer com o Out-of-the-Box-SharePoint" é a minha recomendação.Não só faz você entender a anotomia do SharePoint, mas torna sua vida mais fácil também.Eu vi numerosas implementações onde as webs costume foram desenvolvidas onde existem web partes de Ootb fazendo exatamente a mesma coisa.

Quando todas as opções OOTB estiverem fora, então você começa a desenhar seu diagrama UML, bolhas Balsamiq e criar um novo projeto vazio do SharePoint no Visual Studio.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top