2010-09-20 57 views
4

我有一個類,Document和幾個子類(Invoice,PurchaseOrder等)。我添加了一個鑑別到Document像這樣:流利的NHibernate - 添加鑑別器的問題

public class DocumentMapOverride : IAutoMappingOverride<Document> 
{ 
    public void Override(AutoMapping<Document> mapping) 
    { 
     mapping.DiscriminateSubClassesOnColumn("DocumentType"); 
    } 
} 

我的理解是,如果我創建一個Invoice,它會插入類型名稱到DocumentType列。但是,當我嘗試插入發票時,出現以下異常。

NHibernate.Exceptions.GenericADOException : could not insert: [MyNamespace.Invoice#101][SQL: INSERT INTO "Document" (Version, DocumentNumber, DocumentDate, DbDate, Sender_id, Receiver_id, SenderAlias_id, ReceiverAlias_id, Process_id, Id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] 
    ----> System.Data.SQLite.SQLiteException : Abort due to constraint violation 
Document.DocumentType may not be NULL 

有什麼建議嗎?

  • FluentNHibernate 1.0
  • SQLite的
  • C#/ .Net4.0
+0

http://pastie.org/1175300此NUnit測試顯示我的錯誤。 – 2010-09-23 12:56:37

回答

3

我無法重現該問題。我已經下載了最新版本的FluentNHibernate 1.1 from here和下面的程序細跑:

using System; 
using System.Reflection; 
using FluentNHibernate; 
using FluentNHibernate.Automapping; 
using FluentNHibernate.Automapping.Alterations; 
using FluentNHibernate.Cfg; 
using FluentNHibernate.Cfg.Db; 
using FluentNHibernate.Conventions; 
using FluentNHibernate.Conventions.Instances; 
using NHibernate; 
using NHibernate.Tool.hbm2ddl; 

public interface IEntity 
{ 
    int Id { get; set; } 
} 

public abstract class MyBaseClass : IEntity 
{ 
    public virtual int Id { get; set; } 

    public class MyBaseClassMap : IAutoMappingOverride<MyBaseClass> 
    { 
     public void Override(AutoMapping<MyBaseClass> mapping) 
     { 
      mapping.DiscriminateSubClassesOnColumn("ChildClassType", "MyBaseClassMap"); 
     } 
    } 
} 

public class MyFirstChildClass : MyBaseClass 
{ 
    public virtual string Child1 { get; set; } 
} 

public class MySecondChildClass : MyBaseClass 
{ 
    public virtual string Child2 { get; set; } 
} 

public class PrimaryKeyConvention : IIdConvention 
{ 
    public void Apply(IIdentityInstance instance) 
    { 
     string table = string.Format("{0}_HiLo", instance.EntityType.Name); 
     instance.GeneratedBy.HiLo(table, "next_hi", "100"); 
    } 
} 

public class MyMappingConfig : DefaultAutomappingConfiguration 
{ 
    public override bool ShouldMap(Type type) 
    { 
     if (type.GetInterface(typeof(IEntity).FullName) != null) 
      return true; 

     return false; 
    } 

    public override bool AbstractClassIsLayerSupertype(Type type) 
    { 
     if (type == typeof(IEntity)) 
      return true; 
     return false; 
    } 

    public override bool IsId(Member member) 
    { 
     return member.Name == "Id"; 
    } 

    public override bool IsDiscriminated(Type type) 
    { 
     if (type.IsAssignableFrom(typeof(MyBaseClass)) || type.IsSubclassOf(typeof(MyBaseClass))) 
      return true; 

     return false; 
    } 
} 


public class Program 
{ 
    private static ISession InitializeNHibertnat(Assembly mapAssembly) 
    { 
     var automappingConfiguration = new MyMappingConfig(); 

     var fluentConfiguration = 
      Fluently.Configure().Database(SQLiteConfiguration.Standard.InMemory()); 

     fluentConfiguration = fluentConfiguration 
      .Mappings(m => m.AutoMappings 
           .Add(AutoMap.Assembly(mapAssembly, automappingConfiguration) 
             .Conventions.Add<PrimaryKeyConvention>() 
             .UseOverridesFromAssembly(mapAssembly))) 
      .Mappings(m => m.FluentMappings 
           .AddFromAssembly(mapAssembly)) 
      .Mappings(m => m.HbmMappings 
           .AddFromAssembly(mapAssembly)) 
      .ExposeConfiguration(cfg => cfg.SetProperty("generate_statistics", "true")) 
      .ExposeConfiguration(cfg => cfg.SetProperty("show_sql", "true")) 
      .ExposeConfiguration(cfg => cfg.SetProperty("adonet.batch_size", "1")); 


     var configuration = fluentConfiguration.BuildConfiguration(); 
     var sessionFactory = configuration.BuildSessionFactory(); 
     var session = sessionFactory.OpenSession(); 
     new SchemaExport(configuration).Execute(false, true, false, session.Connection, null); 

     return session; 
    } 

    static void Main() 
    { 
     var mfcc = new MyFirstChildClass(); 
     mfcc.Id = 1; 
     mfcc.Child1 = "Child One"; 

     var mscc = new MySecondChildClass(); 
     mscc.Id = 2; 
     mscc.Child2 = "Child Two"; 

     var Session = InitializeNHibertnat(Assembly.GetExecutingAssembly()); 
     using (var tx = Session.BeginTransaction()) 
     { 
      Session.Save(mfcc); 
      Session.Save(mscc); 
      tx.Commit(); 
     } 
    } 
} 

而這裏的SQL查詢的執行:

NHibernate: select next_hi from MyBaseClass_HiLo 
NHibernate: update MyBaseClass_HiLo set next_hi = @p0 where next_hi = @p1;@p0 = 2, @p1 = 1 
NHibernate: INSERT INTO "MyBaseClass" (Child1, ChildClassType, Id) VALUES (@p0, 'MyFirstChildClass', @p1);@p0 = 'Child One', @p1 = 101 
NHibernate: INSERT INTO "MyBaseClass" (Child2, ChildClassType, Id) VALUES (@p0, 'MySecondChildClass', @p1);@p0 = 'Child Two', @p1 = 102 

在我的測試我也用System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139和有針對性的.NET 4.0此控制檯應用程序在Windows 7 x64上運行它。

+0

謝謝 - 我會嘗試升級到今天或明天的Fluent 1.1。 – 2010-09-27 16:06:50

1

這可以是完全不相關,但是當我試圖此類似映射,我發現Nhibernate的試圖將「ReallyVeryIncrediblyLongNameSpace.Invoice」插入到鑑別器列中,而不僅僅是類型名稱。由於我的專欄不具備所有這些角色的能力,因此失敗了。

我可以看到你的錯誤信息看起來不符合這個,但有時錯誤是誤導性的,所以我認爲它值得一試。