Finding the Primary Key from a ClassMap

2019-03-01 09:48发布

问题:

With Fluent NHibernate, I have an arbitrary ClassMap<T>, I want to be able to find out what property (if any) was set as the primary key.

Example:

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Id(p => p.StupidPrimaryKeyId).GeneratedBy.Identity().Column("StupidPrimaryKeyId");
    }
}

...

//usage
MemberInfo primaryKeyMember = FindPrimaryKey(new PersonMap());

Can anybody tell me what the method body for FindPrimaryKey would have to be in order to return StupidPrimaryKeyId?

Edit: 1/10/12

I originally wanted this because I wanted to know whether or not a detached entity existed in the database, based solely on the primary key (thus my need for knowing the primary key member, not string). I set down this path because a lot of this code already existed in our code base. After rethinking the issue, I've instead realized that the mapping should already take care of that, so using NHibernate.Linq I know have this:

public virtual bool RecordExists(TRecord obj)
{
    var exists = _session.Query<TRecord>().Where(r => r == obj).Any();
    return exists == false;
}

回答1:

So... I inspected Fluent-Nhibernate dll with Reflector and this is what I came-up with:

public string FindPrimaryKey<T>(ClassMap<T> map)
{
    var providersInfo = map.GetType().BaseType.GetField("providers", BindingFlags.Instance | BindingFlags.NonPublic);
    var providersValue = (MappingProviderStore) providersInfo.GetValue(map);
    var Id = providersValue.Id
    var PKName = ((List<string>) Id.GetType().GetField("columns", BindingFlags.Instance | BindingFlags.NonPublic)
                                             .GetValue(Id)).SingleOrDefault();
    return PKName;
 }

Edit by viggity

This is what I was really looking for. Thanks again!

public Member FindPrimaryKey<T>(ClassMap<T> map)
{
    var providersInfo = map.GetType().BaseType.GetField("providers", BindingFlags.Instance | BindingFlags.NonPublic);
    var providersValue = (MappingProviderStore) providersInfo.GetValue(map);
    var id = providersValue.Id;
    var pkMemberInfo = (Member)id.GetType().GetField("member", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(id);
    return pkMemberInfo;
}

end edit

PKName (if the column name assigned explicitly) will obtain the "StupidPrimaryKeyId" column name.

I must say that I'm curious to know why do you need it.