回答

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); 
    } 
} 

約定可以添加到一個自動地圖配置是這樣的:

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

有關詳細信息,在功能NHibernate維基看到Conventions

+0

正是我在找的哦,對於其他任何人您將此行添加到utoPersistenceModelGenerator文件中的GetConventions()方法 c.Add (); – TheAlbear

17

設置長度,任何超過4001將產生一個nvarchar(MAX)...

.WithLengthOf(10000); 

在這裏看到更多的細節......

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

+0

這看起來像它可以用於單個字符串值,但我需要這樣做以接近300個數據字段,所以我正在尋找一種簡單的方法來覆蓋每個nvarchar(255)並將其設置爲nvarchar(Max ) – TheAlbear

6

使用流暢的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過程中造成的,現在你可以裝點字符串屬性 - 和只該財產權 - 在您的實體!

+0

我喜歡這種方式,所以我們可以爲字符串屬性設置特定的最大長度,但我看到有人說它打破POCO,但我不在乎。我認爲你可以通過使用'AttributePropertyConvention '和只有1行代碼'leng =((MyDomain.DBDecorations.StringLength)(myCustomAttrs [0]))來改善這一點。應該用 '代替。 – CallMeLaNN

1

也許您正在使用「NHibernate validator」。如果是的話,功能NHibernate會自動考慮所有的NHibernate的驗證相關數據的註釋,包括字符串長度,不爲空,等

3

其中之一,我發現了一致的方式是:

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; } 
    } 
} 
2

嗨我遇到了這個問題,同樣的問題。我有一個更安全這樣做,因爲我不希望所有字符串字段默認情況下有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); 
     } 
} 

這是隻需要長文本值實體的小部分。也許其他人會發現這有用嗎?

相關問題