使用NHibernate进行一对一映射/使用实体作为PK

时间:2022-09-21 22:56:55

I've got two theoretical domain objects:

我有两个理论域对象:

public class Person { public virtual int Id { get; private set; } }

public class Person {public virtual int Id {get;私人集; }}

public class PersonMap : ClassMap<Person>
{
    public PersonMap() { Id( x => x.Id ); }
}

public class DriversLicense
{
    public virtual Person Person { get; set; }
    public virtual string State { get; set; }
}

public class DriversLicenseMap : ClassMap<DriversLicense>
{
    public DriversLicenseMap()
    {
        References( x => x.Person );
        Map( x => x.State );
    }
}

Where the Person object is to be used as the PK on DriversLicense. I don't want the Person object to have any knowledge of DriversLicense so the relationship is maintained strictly in the DriversLicense class. There is exactly one DriversLicense per person.

将Person对象用作DriversLicense上的PK的位置。我不希望Person对象具有DriversLicense的任何知识,因此关系在DriversLicense类中严格维护。每人只有一个DriversLicense。

When setup this way I'm getting the following exception:

当以这种方式设置时,我得到以下异常:

System.Xml.Schema.XmlSchemaValidationException: The element 'class' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'property' in namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'meta, jcs-cache, cache, id, composite-id' in namespace 'urn:nhibernate-mapping-2.2'.

System.Xml.Schema.XmlSchemaValidationException:命名空间'urn:nhibernate-mapping-2.2'中的元素'class'在命名空间'urn:nhibernate-mapping-2.2'中具有无效的子元素'property'。期望的可能元素列表:名称空间'urn:nhibernate-mapping-2.2'中的'meta,jcs-cache,cache,id,composite-id'。

Adding an Id property to the DriversLicense type fixes the problem.

将Id属性添加到DriversLicense类型可以解决问题。

Is there a way to use the Person itself as the primary key in the DriversLicense table so that the underlying table just uses the Person.Id for it's primary key?

有没有办法使用Person本身作为DriversLicense表中的主键,以便底层表只使用Person.Id作为它的主键?

2 个解决方案

#1


You can use a composite id key ? http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-compositeid http://nhibernate.info/doc/nh/en/index.html#components-compositeid

你可以使用复合id键吗? http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-compositeid http://nhibernate.info/doc/nh/en/index.html#components-compositeid

#2


@Matthieu got me on the right track with composite keys. I had to use the UseCompositeId() method and then override Equals & GetHashCode for the Drivers License object.

@Matthieu用复合键让我走上了正确的轨道。我不得不使用UseCompositeId()方法,然后为Drivers License对象重写Equals和GetHashCode。

Here's how it looks in fluent NHibernate:

以下是流畅的NHibernate的外观:

public class DriversLicense
{
        public virtual Person Person { get; set; }
        public virtual string State { get; set; }

        public override bool Equals( object obj )
        {
            if( ReferenceEquals( obj, null ) ) return false;

            // Cast, instead of 'as' throws runtime exception when obj is not an 
            // DriversLicense.
            var comp = (DriversLicense) obj;

            if( Person == null || comp.Person == null )
                return false;

            return Person.Equals( comp.Person );
        }

        public override int GetHashCode() 
        {
            return Account == null ? -1 : Account.GetHashCode(); 
        }
}

public class DriversLicenseMap : ClassMap<DriversLicense>
{
        public DriversLicenseMap()
        {
                UseCompositeId().WithKeyReference( x => x.Person );
                Map( x => x.State );
        }
}

#1


You can use a composite id key ? http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-compositeid http://nhibernate.info/doc/nh/en/index.html#components-compositeid

你可以使用复合id键吗? http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-compositeid http://nhibernate.info/doc/nh/en/index.html#components-compositeid

#2


@Matthieu got me on the right track with composite keys. I had to use the UseCompositeId() method and then override Equals & GetHashCode for the Drivers License object.

@Matthieu用复合键让我走上了正确的轨道。我不得不使用UseCompositeId()方法,然后为Drivers License对象重写Equals和GetHashCode。

Here's how it looks in fluent NHibernate:

以下是流畅的NHibernate的外观:

public class DriversLicense
{
        public virtual Person Person { get; set; }
        public virtual string State { get; set; }

        public override bool Equals( object obj )
        {
            if( ReferenceEquals( obj, null ) ) return false;

            // Cast, instead of 'as' throws runtime exception when obj is not an 
            // DriversLicense.
            var comp = (DriversLicense) obj;

            if( Person == null || comp.Person == null )
                return false;

            return Person.Equals( comp.Person );
        }

        public override int GetHashCode() 
        {
            return Account == null ? -1 : Account.GetHashCode(); 
        }
}

public class DriversLicenseMap : ClassMap<DriversLicense>
{
        public DriversLicenseMap()
        {
                UseCompositeId().WithKeyReference( x => x.Person );
                Map( x => x.State );
        }
}