4 Stimmen

Fluent NHibernate - Probleme beim Hinzufügen eines Diskriminators

Ich habe eine Klasse, Document und mehrere Unterklassen ( Invoice , PurchaseOrder usw.). Ich habe ein Unterscheidungsmerkmal hinzugefügt zu Document etwa so:

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

Wenn ich also eine Invoice wird der Typname in die Datei DocumentType Spalte. Wenn ich jedoch versuche, die Rechnung einzufügen, erhalte ich die folgende Ausnahme.

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

Irgendwelche Vorschläge?

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

3voto

Darin Dimitrov Punkte 990883

Ich war nicht in der Lage, das Problem zu reproduzieren. Ich habe die neueste Version von FluentNHibernate 1.1 von hier und das folgende Programm lief problemlos:

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

Und hier sind die ausgeführten SQL-Abfragen:

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

In meinem Test habe ich auch System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139 und zielte auf .NET 4.0 für diese Konsolenanwendung. Sie wurde unter Windows 7 x64 ausgeführt.

1voto

Jonny Cundall Punkte 2487

Dies mag völlig irrelevant sein, aber als ich eine ähnliche Zuordnung wie diese versuchte, stellte ich fest, dass Nhibernate versuchte, "ReallyVeryIncrediblyLongNameSpace.Invoice" in die Diskriminatorspalte einzufügen, anstatt nur den Typnamen. Da meine Spalte nicht über die Kapazität für all diese Zeichen verfügte, schlug der Versuch fehl.

Ich sehe, dass Ihre Fehlermeldung nicht damit übereinzustimmen scheint, aber manchmal sind Fehler irreführend, so dass ich dachte, es sei einen Versuch wert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X