2011-07-31 37 views
4

我想創建一個鑑別器列。該列將保存可用的許多狀態之一。就像我的代碼將顯示每個狀態都有一個名稱以及一個背景顏色。每個狀態共享相同的基類。使用歧視與流利NHibernate

這裏是我的代碼:

public class Item 
{ 
    public virtual int Id { get; set; } 
    public virtual Status ItemStatus { get; set; } 
} 

public abstract class Status 
{ 
    private readonly int _id; 
    public static readonly Status Foo = new FooStatus(1); 
    public static readonly Status Bar = new BarStatus(2); 

    public Status() 
    { 

    } 

    protected Status(int id) 
    { 
     _id = id; 
    } 

    public virtual int Id { get { return _id; } } 
    public abstract string Name { get; } 
    public abstract string BackgroundColor { get; } 
} 

public class FooStatus : Status 
{ 
    public FooStatus() 
    { 

    } 

    public FooStatus(int id) 
     : base(id) 
    { 

    } 

    public override string Name 
    { 
     get { return "Foo Status"; } 
    } 

    public override string BackgroundColor 
    { 
     get { return "White"; } 
    } 
} 

public class BarStatus : Status 
{ 
    public BarStatus() 
    { 

    } 

    public BarStatus(int id) 
     : base(id) 
    { 

    } 

    public override string Name 
    { 
     get { return "Bar Status"; } 
    } 

    public override string BackgroundColor 
    { 
     get { return "Black"; } 
    } 
} 

這裏是我的映射:

public class ItemMap : ClassMap<Item> 
{ 
    public ItemMap() 
    { 
     Id(x => x.Id).GeneratedBy.Identity(); 

     DiscriminateSubClassesOnColumn<int>("ItemStatus", 0).AlwaysSelectWithValue(); 
    } 
} 

從本質上講,我想的是,如果我設置ItemStatusStatus.Foo那麼ItemStatus列將有值爲1.我現在所擁有的不會拋出任何例外,但總是插入ItemStatus作爲0

這是插入代碼我使用:

 using (var session = sessionFactory.OpenSession()) 
     using (var transaction = session.BeginTransaction()) 
     { 
      var item = new Item 
          { 
           ItemStatus = Status.Foo 
          }; 
      session.Save(item); 
      transaction.Commit(); 

      var firstItem = session.Get<Item>(1); 
      Console.WriteLine(firstItem.ItemStatus.Name); 
     } 

我在哪裏可以使用FNH這個話題讀了?

之前有人建議檢查谷歌我沒有搜索幾件事,但沒有在哪裏可以找到一個完整的例子。

回答

3

SubclassMap會是這個樣子:

public class FooStatusMap : SubclassMap<FooStatus> 
{ 
    public FooStatusMap() 
    { 
     DiscriminatorValue(1); 
    } 
} 

這就是所謂的「表每類層次結構,」你是對的它看起來並不像有它了許多資源那裏。

相信如果你沒有在SubclassMapDiscriminatorValue,NHibernate的嘗試通過查看被映射的子類的名稱,如果它在鑑別列中的值相匹配看到歧視。

+1

啊,我錯過了。當我爲每個狀態創建一個子類映射時,NHibernate仍將'0'作爲我的'ItemStatus'插入。這一定是由於我將'baseClassDiscriminator'設置爲0的事實。但是,如果我刪除'baseClassDiscriminator',構建我的配置時,NHibernate會拋出異常「無法將鑑別器值格式化爲實體NHibernateDiscriminator.Domain.Item的SQL字符串」 。 – User

+0

@用戶:有趣。我會設置這個映射,看看我是否可以複製它。 –

+0

@用戶:在數據庫中,數據類型是整數嗎? –

0

我不會寫所有你可以做這個子類子圖,而不是

public class FooMap: ClassMap<T> 
{ 
//other mapping 
DiscriminateSubClassesOnColumn("DiscriminatorColumn") 
.SubClass<Foo1>(m => { }) 
.SubClass<Foo2>(m => { }) 
.SubClass<Foo3>(m => { }); 
} 

希望幫助

+1

我最初的實現是使用這種方法,但已經過時了。 – User

0

如果你打開具有派生類的類名鑑別列,你可以通過自動映射來實現。

在你的會話工廠:

private static ISessionFactory CreateSessionFactory() 
{ 
    var cfg = new MyMappingConfiguration(); 
    return Fluently.Configure() 
    .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("MyConnectionKey")).FormatSql().ShowSql() 
      ) 
    .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Status>(cfg) 
    .IncludeBase<Status>() 
    .Conventions.Add<PrimaryKeyConvention>())) 
    .BuildSessionFactory(); 
} 

然後添加MyMappingConfiguration覆蓋:

public class MappingConfiguration : DefaultAutomappingConfiguration 
{ 
    public override bool IsId(Member member) 
    { 
     return member.Name == member.DeclaringType.Name + "Id"; 
    } 

    public override bool IsDiscriminated(Type type) 
    { 
     return true; 
    } 
} 

希望使得h