當你設置一個字符串值流利的NHibernate它alwasy將數據庫值設置爲Nvarchar(255),我需要存儲相當多的基於用戶輸入和255的長字符串是不切實際的。覆蓋流暢的NHibernate的長文本字符串nvarchar(MAX)不nvarchar(255)
只是添加這個是automapper的問題,因爲我使用流利的NHibernate來構建數據庫。
當你設置一個字符串值流利的NHibernate它alwasy將數據庫值設置爲Nvarchar(255),我需要存儲相當多的基於用戶輸入和255的長字符串是不切實際的。覆蓋流暢的NHibernate的長文本字符串nvarchar(MAX)不nvarchar(255)
只是添加這個是automapper的問題,因爲我使用流利的NHibernate來構建數據庫。
添加此約定將設置字符串屬性的默認長度爲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維基看到Conventions。
設置長度,任何超過4001將產生一個nvarchar(MAX)...
.WithLengthOf(10000);
在這裏看到更多的細節......
http://serialseb.blogspot.com/2009/01/fluent-nhibernate-and-nvarcharmax.html
這看起來像它可以用於單個字符串值,但我需要這樣做以接近300個數據字段,所以我正在尋找一種簡單的方法來覆蓋每個nvarchar(255)並將其設置爲nvarchar(Max ) – TheAlbear
使用流暢的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; }
}
}
如果這可以工作,我們必須在每個字符串中的獨立控制,我們可以直接在我們的實體中指定它。
在我將數據庫從應用程序中分離出來之前,讓我指出這不是一個特別的數據庫指令(我沒有調用屬性'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過程中造成的,現在你可以裝點字符串屬性 - 和只該財產權 - 在您的實體!
我喜歡這種方式,所以我們可以爲字符串屬性設置特定的最大長度,但我看到有人說它打破POCO,但我不在乎。我認爲你可以通過使用'AttributePropertyConvention
也許您正在使用「NHibernate validator」。如果是的話,功能NHibernate會自動考慮所有的NHibernate的驗證相關數據的註釋,包括字符串長度,不爲空,等
其中之一,我發現了一致的方式是:
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);
}
}
這是隻需要長文本值實體的小部分。也許其他人會發現這有用嗎?
正是我在找的哦,對於其他任何人您將此行添加到utoPersistenceModelGenerator文件中的GetConventions()方法 c.Add(); –
TheAlbear