占优流利的NHibernate的长文本字符串为nvarchar(MAX)不为nvarchar(255)
-
23-09-2019 - |
题
在任何你设置一个字符串值,用流利的NHibernate它alwasy设置DB瓦莱斯为nvarchar(255),我需要存储相当多的是基于用户输入和255是不切实际的长字符串的。
我想补充这是因为我使用功能NHibernate建立数据库automapper的问题。
解决方案
添加此惯例将字符串属性的默认长度设置为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);
}
}
约定可以添加到一个自动地图配置是这样的:
Fluently.Configure()
.Mappings( m =>
m.AutoMappings.Add( AutoMap.AssemblyOf<Foo>()
.Conventions.Add<StringColumnLengthConvention >()))
有关的更多信息,请参阅约定在功能NHibernate维基的。
其他提示
设置长度以任何超过4001将产生一个nvarchar(MAX)...
.WithLengthOf(10000);
请参阅此处更详细...
http://serialseb.blogspot.com/2009/ 01 /流利-的nhibernate和 - nvarcharmax.html
使用功能NHibernate Automapper,一个很快意识到对于varchar列的出的现成的行为是不理想的。首先你会发现,每一个字符串属性导出为varchar(255),你需要做一个列是VARCHAR(最大值)。但是,理想情况下,你就不必让每一个串一个varchar(最大),对不对?所以,你低着头,寻找到对过程施加控制的最好办法,而不在作怪......
打破各种优雅的方式摆脱了良好的践踏路径如果你想有不同的长度指定你生成的数据库VARCHAR列,你看约定类做到这一点。您可以尝试创建名称 - 特定条件或一般使用一些命名模式,您在约定类的内部检测。
都不是理想的。用于指示代码的另一部分预期规范的目的超载的名称是unfortunate-你的名字应该只是一个名字。你也应该在每次需要添加或修改有限长度类属性的时间来修改公约的代码。所以你怎么能写一个约定类,让你控制,并提供了控制一个简单而优雅的方式?
这将会是甜的,如果你可以只的装修的你的财产像我一样的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; }
}
}
如果这可以工作,我们必须在每个字符串中的独立控制,而且我们希望能够直接在我们的实体指定。
在我重新开始从应用数据库的分离漩涡,让我指出,这并不是特意一数据库指令(I由不调用属性“的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;
}
}
}
最后,我们需要使用一个字符串长度约定使用实体的财产装饰。这部分可能看起来并不漂亮,但它的工作,好消息是,你将不必在它再看看!
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);
}
}
}
每当你想要的特定长度ExportSchema期间导致加入本公约的自动映射配置有你有它 - 现在你可以装点字符串属性 - 和仅该项财产的权利在实体!
其中一个一致的方式,我发现是:
Map(x => x.LongText, "LongText").CustomType<VarcharMax>().Nullable();
,其中VarcharMax和类
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; }
}
}
您好我碰到这个问题就来了,同样的问题。我有一个轻微的安全的做这件事,因为我不希望所有字符串字段默认情况下有10000个字符的方式。
首先,我注册功能NHibernate一些替换
...//snip
....Mappings(m => m.AutoMappings.Add(
AutoMap.AssemblyOf<Account>()
//Use my mapping overrides here
.UseOverridesFromAssemblyOf<MyMappingOverride>()
.Conventions.Add(new MyConventions()).IgnoreBase<Entity>
))
我的映射倍率类看起来像这样:
public class MyMappingOverride : IAutoMappingOverride<MyClass> {
public void Override(AutoMapping<MyClass> mapping) {
mapping.Map(x => x.LongName).Length(765);
}
}
此仅需要具有长的文本值实体的小的子集。也许有些人会觉得这有用吗?
可能使用的是 “ NHibernate的验证” 为好。如果是,功能NHibernate会考虑所有NHibernate的验证器自动相关数据的注解,包括字符串的长度,不为空,等等的。