使用Fluent NHibernate,我似乎无法为以下(看似简单和常见)用例设计必要的自动化约定:
public class MyClass
{
private int _specialIdentityField
private string _firstname;
public Id { get { return _specialIdentityField; }; }
public virtual string Firstname
{
get
{
return _firstname;
}
set
{
_firstname = value;
}
}
}
public class OtherClass
{
private int _specialIdentityField
private string _lastname;
public Id { get { return _specialIdentityField; }; }
public virtual string Lastname
{
get
{
return _lastname;
}
set
{
_lastname = value;
}
}
}
所需的映射是这样的:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="field.camelcase-underscore" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="MyClass" table="`MyClass`">
<id name="_specialIdentityField" type="System.Int32" access=field>
<column name="Id" />
<generator class="identity" />
</id>
<property name="Firstname" type="System.String">
<column name="Firstname" />
</property>
</class>
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="OtherClass" table="`OtherClass`">
<id name="_specialIdentityField" type="System.Int32" access=field>
<column name="Id" />
<generator class="identity" />
</id>
<property name="Lastname" type="System.String">
<column name="Lastname" />
</property>
</class>
</hibernate-mapping>
基本上规则是:
完全绊倒我的部分是与身份相关的元素的约定映射(显然,属性的约定映射是完全标准的票价)。我遇到的问题是如何告诉FNH约定我的身份字段是固定名称。我能找到的所有常规覆盖似乎都假设在表示身份的属性和其底层支持字段的名称之间总会存在一些关系(例如,我可以为其设置'自定义前缀'支持领域,但似乎无法看到我怎么能说“这总是支持领域的名称”。)
对我来说很明显如何通过显式映射(以及使用XML映射文件)实现这一点,但对我来说如何通过FNH中基于约定(自动映射)的映射来实现这一点并不明显。
这不是一个非典型的用例,所以我必须忽略一些非常明显的东西。来自任何FNH大师的想法表示赞赏!
答案 0 :(得分:1)
编辑:看一下IAutomappingConfiguration界面。创建自己的实现或覆盖DefaultAutomappingConfiguration类。
public virtual bool IsId(Member member)
{
return member.Name.Equals("id", StringComparison.InvariantCultureIgnoreCase);
}
然后将其添加到初始化:
Fluently.Configure( Configuration )
.Mappings( cfg =>
{ cfg.AutoMappings.Add( IAutomappingConfigurationInstance )}
===============================================
史蒂夫,我想我知道你要做什么。我使用Proteus和FNH自动化。为了用id做诀窍,我在Proteus周围创建了一个包装器,它做了两件事:
1)映射ID
2)隐藏ID的设置者
public abstract class EntityObject<TEntity> : IdentityPersistenceBase<TEntity, Guid>, IEntity
where TEntity : class, IEntity
{
public virtual Guid Id
{
get { return _persistenceId; }
}
Guid IIdentifiedEntity<Guid>.Id
{
get { return _persistenceId; }
set { _persistenceId = value; }
}
public virtual int Version
{
get { return _persistenceVersion; }
set { _persistenceVersion = value; }
}
}
要避免属性IsTransient被持久化+其他东西你可以创建MappingAlternation:
public class EntityAlteration : IAutoMappingAlteration
{
public void Alter( AutoPersistenceModel model )
{
model.OverrideAll( map =>
{
Type recordType = map.GetType().GetGenericArguments().Single();
if( recordType.BaseType.Name == "EntityObject`1" )
{
Type changeType = typeof( Change<> ).MakeGenericType( recordType );
var change = ( IChange )Activator.CreateInstance( changeType );
change.Go( map );
}
} );
}
}
interface IChange
{
void Go( object mapObject );
}
class Change<TRecord> : IChange where TRecord : EntityObject<TRecord>
{
void IChange.Go( object mapObject )
{
var map = ( AutoMapping<TRecord> )mapObject;
map.Id( x => x.Id ).GeneratedBy.Guid().Access.Property();
map.IgnoreProperty( x => x.IsTransient );
}
}
PS:我真的很想念你在网络空间活跃的时候。 2年前,这是令人兴奋的Summer和Authumn ......