为长文本字符串覆盖流畅的NHibernate nvarchar(MAX)不是nvarchar(255)

The*_*ear 40 c# nhibernate fluent-nhibernate automapping sharp-architecture

当你在流畅的NHibernate中设置字符串值时,它会将数据库值设置为Nvarchar(255),我需要存储相当多的基于用户输入的长字符串,而255是不切实际的.

只是为了添加这个是自动播放器的问题,因为我使用流畅的NHibernate来构建数据库.

Lac*_*che 33

添加此约定会将字符串属性的默认长度设置为10000.正如其他人所说,这将是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

可以将约定添加到自动配置中,如下所示:

Fluently.Configure()
    .Mappings( m =>
        m.AutoMappings.Add( AutoMap.AssemblyOf<Foo>()
        .Conventions.Add<StringColumnLengthConvention >()))
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅Fluent NHibernate wiki中的约定.


Rus*_*ngs 17

将长度设置为4001以上将生成NVarchar(MAX)...

.WithLengthOf(10000);
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参见此处

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


Ben*_*son 6

使用Fluent Nhibernate Automapper,可以快速意识到varchar列的开箱即用行为不太理想.首先,您发现每个字符串属性都导出为varchar(255),您需要将列设置为varchar(max).但理想情况下,您不必将每个字符串都设为varchar(max),对吧?因此,你要找到最好的方法来找到最好的方法来控制整个过程而不会打破各种优雅的模式......

如果要以不同的长度指定生成的数据库varchar列,可以查看约定类以实现它.您可以尝试创建特定于名称的条件,或者通常使用在约定类中检测到的某些命名模式.

两者都不理想.为了在代码的另一部分中指示预期的规范而重载名称是不幸的 - 您的名字应该只是一个名称.每次需要添加或修改有限长度的类属性时,也不必修改约定代码.那么如何编写一个可以控制并以简单优雅的方式提供控件的约定类呢?

如果你能像我在Body身上所做的那样装饰你的财产,那就太好了:

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果这可行,我们可以独立控制每个字符串,并且我们可以直接在我们的实体中指定它.

在我开始对应用程序中数据库分离的漩涡之前,让我指出这不是一个特别的数据库指令(我指出不调用属性'Varchar').我更喜欢把它描述为System.string的扩充,而在我自己的小宇宙中,我很高兴.最重要的是,我想要一个方便!

为此,我们需要定义我们想要使用的装饰:

using System;
namespace MyDomain.DBDecorations
{

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

最后,我们需要使用字符串长度约定来使用实体的属性修饰.这部分可能看起来不太漂亮,但它确实起作用了,好消息是你不必再看一遍了!

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

将此约定添加到您的自动化配置中,只要您想在ExportSchema期间生成特定长度,现在您只需装饰字符串属性 - 并且只能在您的实体中装饰该属性!