当 Id 位于抽象基类中时,NHibernate 映射出现问题

发布于 2024-10-31 09:36:19 字数 5367 浏览 1 评论 0原文

我对 nhibernate 很陌生,在遇到这个问题之前我一直做得很好,它看起来像一个 NHibernate bug,但作为它的新手,这肯定是我的错

让这个基类来完成所有的 Id 和相等性东西

    public abstract class ObjetoConId
{
    public ObjetoConId()
    {
        Id=NewId();
    }

    public virtual Guid Id {get;private set;}

    public override bool Equals(object o)
    {
        if (Object.ReferenceEquals(this,o))
            return true;

        if (o==null) return false;

        ObjetoConId oId;

        oId= o as ObjetoConId;
        if (!Object.ReferenceEquals(oId,null))
            return (Id.Equals(oId.Id));

        return (base.Equals(o));
    }
    public override int GetHashCode()
    {
        byte[] bId;

        bId=Id.ToByteArray();

        return  ((Int32)(bId[8]^bId[12])<<24) +
                ((Int32)(bId[9]^bId[13])<<16) + 
                ((Int32)(bId[10]^bId[14])<<8) + 
                ((Int32)(bId[11]^bId[15]));
    }

    public virtual bool Equals(ObjetoConId o)
    {
        if (Object.ReferenceEquals(this,o))
            return true;

        if (Object.ReferenceEquals(o,null)) return false;
            return (Id.Equals(o.Id));
    }

    public virtual string toString() 
    {
        return this.GetType().FullName
        + "[id=" + Id + "]";
    }

    protected virtual Guid NewId()
    {
        return GuidComb.NewGuid();
    }

    public static bool operator == (ObjetoConId x,ObjetoConId y)
    {
        if(Object.ReferenceEquals(x,y))
            return true;
        if(Object.ReferenceEquals(x,null))
            return false;
        return x.Equals(y);
    }

    public static bool operator != (ObjetoConId x,ObjetoConId y)
    {
        return !(x==y);
    }

    /// <summary>
    /// Metodo interno para permitir el testing
    /// </summary>
    /// <param name="id"></param>
    internal void setId(Guid id)
    {
        Id=id;
    }
}

和这个实体

public class Propiedad : ObjetoConId,IPropiedad
{
    [Obsolete("Persistance Constructor only")]
    public Propiedad ()
    {
    }


    public Propiedad (IList<IDescripcionCalificada> descripciones)
    {
        Descripciones=new Dictionary<string,IDescripcionCalificada>(descripciones.Count);
        foreach(IDescripcionCalificada d in descripciones)
            Descripciones.Add(d.Nombre,d);
    }


    #region IPropiedad implementation
    public virtual IDictionary<string, IDescripcionCalificada> Descripciones {get;private set;}

    #endregion  

}

以及这个映射

    public class MapeoPropiedad : ClassMap<Propiedad>
{ 
    public MapeoPropiedad()
    {
        Id(x => x.Id).Column("pro_id").GeneratedBy.Assigned();
        HasMany<DescripcionCalificada>(x => x.Descripciones)
        .Cascade.SaveUpdate()
        .AsMap<string>(index => index.Nombre)
        ;
    }
}

对它的测试是

[TestFixture]
public class TestPropiedadPersistencia
{

    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {

        string connectionString="Server=127.0.0.1;Database=Ana;User ID=dev-test;Password=dev-test;";

        fcfg=Fluently.Configure()
            .Database(PostgreSQLConfiguration.PostgreSQL82.ConnectionString(connectionString))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<MapeoPropiedad>());


        fcfg.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false, true));
        sessions=fcfg.BuildSessionFactory();
    }


    ISessionFactory sessions;
    FluentConfiguration fcfg;



    [TestFixtureTearDown]
    public void TestFixtureTearDown()
    {
        fcfg.ExposeConfiguration(cfg => new SchemaExport(cfg).Drop(false, true));
        sessions.Close();
        sessions = null;
        fcfg = null;
    }


    [Test]
    public void CanCorrectlyMapPropiedad()
    {
        DescripcionCalificada descri1=new DescripcionCalificada("descri",new Descripcion("Esta es la descri"));
        DescripcionCalificada descri2=new DescripcionCalificada("descriLarga",new Descripcion("Esta es la descriLarga"));
        Dictionary<string,IDescripcionCalificada> descris=new Dictionary<string, IDescripcionCalificada>(2);

        descris.Add(descri1.Nombre,descri1);
        descris.Add(descri2.Nombre,descri2);

        new PersistenceSpecification<Propiedad>(sessions.OpenSession(),new CustomEqualityComparer() )
            .CheckProperty(c => c.Descripciones,descris)
            .VerifyTheMappings();
    }

}

事情是测试失败,除非我将 Not.LazyLoad() 放入映射中 它给出了一个映射错误,

Ana.Nucleo.Lenguaje.Test.TestDescripcionCalificadaPersistencia (TestFixtureSetUp):
FluentNHibernate.Cfg.FluentConfigurationException : An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.


  ----> NHibernate.InvalidProxyTypeException : The following types may not be used as proxies:
Ana.Catalogacion.Implementacion.Propiedad: method setId should be 'public/protected virtual' or 'protected internal virtual'

没有延迟加载,它就会通过,如果我将 Id 属性放在 Propiedad 类中,而不是从 ObjetoConID 继承,它也会通过,无论有没有 Not.LazyLoad()。

任何人都可以确认这是一个 NH bug,或者任何帮助将不胜感激

编辑:

我发现了问题,我的错。我错过了 setId 内部函数没有受到虚拟保护,并且与 Id 属性的 setter 混淆,因此误解了执行

Fer

I'm quite new to nhibernate, I was doing all right until I face this problem, It looks like a NHibernate bug, but being a newbie with it, it can certainly be my fault

Having this base class to do all the Id and equality stuff

    public abstract class ObjetoConId
{
    public ObjetoConId()
    {
        Id=NewId();
    }

    public virtual Guid Id {get;private set;}

    public override bool Equals(object o)
    {
        if (Object.ReferenceEquals(this,o))
            return true;

        if (o==null) return false;

        ObjetoConId oId;

        oId= o as ObjetoConId;
        if (!Object.ReferenceEquals(oId,null))
            return (Id.Equals(oId.Id));

        return (base.Equals(o));
    }
    public override int GetHashCode()
    {
        byte[] bId;

        bId=Id.ToByteArray();

        return  ((Int32)(bId[8]^bId[12])<<24) +
                ((Int32)(bId[9]^bId[13])<<16) + 
                ((Int32)(bId[10]^bId[14])<<8) + 
                ((Int32)(bId[11]^bId[15]));
    }

    public virtual bool Equals(ObjetoConId o)
    {
        if (Object.ReferenceEquals(this,o))
            return true;

        if (Object.ReferenceEquals(o,null)) return false;
            return (Id.Equals(o.Id));
    }

    public virtual string toString() 
    {
        return this.GetType().FullName
        + "[id=" + Id + "]";
    }

    protected virtual Guid NewId()
    {
        return GuidComb.NewGuid();
    }

    public static bool operator == (ObjetoConId x,ObjetoConId y)
    {
        if(Object.ReferenceEquals(x,y))
            return true;
        if(Object.ReferenceEquals(x,null))
            return false;
        return x.Equals(y);
    }

    public static bool operator != (ObjetoConId x,ObjetoConId y)
    {
        return !(x==y);
    }

    /// <summary>
    /// Metodo interno para permitir el testing
    /// </summary>
    /// <param name="id"></param>
    internal void setId(Guid id)
    {
        Id=id;
    }
}

and this entity

public class Propiedad : ObjetoConId,IPropiedad
{
    [Obsolete("Persistance Constructor only")]
    public Propiedad ()
    {
    }


    public Propiedad (IList<IDescripcionCalificada> descripciones)
    {
        Descripciones=new Dictionary<string,IDescripcionCalificada>(descripciones.Count);
        foreach(IDescripcionCalificada d in descripciones)
            Descripciones.Add(d.Nombre,d);
    }


    #region IPropiedad implementation
    public virtual IDictionary<string, IDescripcionCalificada> Descripciones {get;private set;}

    #endregion  

}

and this mapping

    public class MapeoPropiedad : ClassMap<Propiedad>
{ 
    public MapeoPropiedad()
    {
        Id(x => x.Id).Column("pro_id").GeneratedBy.Assigned();
        HasMany<DescripcionCalificada>(x => x.Descripciones)
        .Cascade.SaveUpdate()
        .AsMap<string>(index => index.Nombre)
        ;
    }
}

The test for it is

[TestFixture]
public class TestPropiedadPersistencia
{

    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {

        string connectionString="Server=127.0.0.1;Database=Ana;User ID=dev-test;Password=dev-test;";

        fcfg=Fluently.Configure()
            .Database(PostgreSQLConfiguration.PostgreSQL82.ConnectionString(connectionString))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<MapeoPropiedad>());


        fcfg.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false, true));
        sessions=fcfg.BuildSessionFactory();
    }


    ISessionFactory sessions;
    FluentConfiguration fcfg;



    [TestFixtureTearDown]
    public void TestFixtureTearDown()
    {
        fcfg.ExposeConfiguration(cfg => new SchemaExport(cfg).Drop(false, true));
        sessions.Close();
        sessions = null;
        fcfg = null;
    }


    [Test]
    public void CanCorrectlyMapPropiedad()
    {
        DescripcionCalificada descri1=new DescripcionCalificada("descri",new Descripcion("Esta es la descri"));
        DescripcionCalificada descri2=new DescripcionCalificada("descriLarga",new Descripcion("Esta es la descriLarga"));
        Dictionary<string,IDescripcionCalificada> descris=new Dictionary<string, IDescripcionCalificada>(2);

        descris.Add(descri1.Nombre,descri1);
        descris.Add(descri2.Nombre,descri2);

        new PersistenceSpecification<Propiedad>(sessions.OpenSession(),new CustomEqualityComparer() )
            .CheckProperty(c => c.Descripciones,descris)
            .VerifyTheMappings();
    }

}

The thing is that the test fails unless I put Not.LazyLoad() in the mapping
It gives a mapping error

Ana.Nucleo.Lenguaje.Test.TestDescripcionCalificadaPersistencia (TestFixtureSetUp):
FluentNHibernate.Cfg.FluentConfigurationException : An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.


  ----> NHibernate.InvalidProxyTypeException : The following types may not be used as proxies:
Ana.Catalogacion.Implementacion.Propiedad: method setId should be 'public/protected virtual' or 'protected internal virtual'

without lazy loading it pass, and if I put the Id property in the Propiedad class and not inherit from ObjetoConID it also pass, with and without the Not.LazyLoad().

Anyone can confirm this is a NH bug, or any help will be appreciated

EDIT:

I've found the problem, my fault. I missed the setId internal function not being virtual protected and confused with the setter of the Id property, and thus missunderstood the execption

Fer

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云巢 2024-11-07 09:36:19

我发现问题了,是我的错。我错过了 setId 内部函数没有受到虚拟保护,并且与 Id 属性的 setter 混淆,因此误解了执行

I've found the problem, my fault. I missed the setId internal function not being virtual protected and confused with the setter of the Id property, and thus missunderstood the execption

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文