Fluent NHibernate:按照约定映射 HasManyToMany
我正在使用 Fluent NHibernate 的 AutoMap 功能来映射我的实体。我的大多数实体都继承自基类 Entity
,该基类具有属性 public IList
。
标签位于数据库中的单独表中,因此我使用多对多关系。但是 Fluent NHibernate 创建一对多关系的映射。
我想编写一个约定来重写这些映射,以便在该类继承自 Entity
时使用 HasManyToMany(...)
。这可能吗?如何实现?
该约定可以依赖于属性的类型或其名称。
一些示例代码:
// entities
public class Entity
{
public virtual int Id { get; set; }
// ... some other properties
public virtual IList<Tag> { get; set; }
}
public class Tag
{
public virtual int Id { get; set; }
public virtual string TagName { get; set; }
}
public class Event : Entity
{
// ... some properties
}
// Fluent NHibernate configuration
public static ISessionFactory CreateSessionFactory()
{
var config = new CustomAutomappingConfiguration();
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("Sql")))
.Mappings(m =>
{
m.AutoMappings.Add(AutoMap.AssemblyOf<Event>(config)
.IgnoreBase<Entity>()
.Conventions.Add<CustomForeignKeyConvention>()
.Conventions.Add<CustomManyToManyTableNameConvention>();
})
.BuildSessionFactory();
}
I'm using Fluent NHibernate's AutoMap feature to map my entities. Most of my entities inherit from a base class Entity
which has a property public IList<Tag> Tags
.
The tags are in a separate table in the database, so I use a many-to-many relation. But Fluent NHibernate creates mappings for a one-to-many relation.
I'd like to write a convention to override these mappings to use HasManyToMany(...)
if the class inherits from Entity
. Is this possible and how?
The convention could either rely on the property's type or its name.
Some code for illustration:
// entities
public class Entity
{
public virtual int Id { get; set; }
// ... some other properties
public virtual IList<Tag> { get; set; }
}
public class Tag
{
public virtual int Id { get; set; }
public virtual string TagName { get; set; }
}
public class Event : Entity
{
// ... some properties
}
// Fluent NHibernate configuration
public static ISessionFactory CreateSessionFactory()
{
var config = new CustomAutomappingConfiguration();
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("Sql")))
.Mappings(m =>
{
m.AutoMappings.Add(AutoMap.AssemblyOf<Event>(config)
.IgnoreBase<Entity>()
.Conventions.Add<CustomForeignKeyConvention>()
.Conventions.Add<CustomManyToManyTableNameConvention>();
})
.BuildSessionFactory();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您无法通过约定来完成映射。但是,如果您想在实体和标签之间保留一个链接表,可以执行以下操作:
请注意,我将
IgnoreBase()
更改为IncludeBase()< /代码>。这将添加一个实体表,但会保留一个链接表。通过此映射,您将获得下表 DDL:
如果您选择对每个子类执行
Override
,则每个子类将拥有一个链接表。I don't think you can accomplish the mapping with conventions. However, if you want to keep one linking table between the entities and tags, you can do the following:
Notice that I changed
IgnoreBase<Entity>()
toIncludeBase<Entity>()
. This will add an Entity table, but will keep one linking table. With this mapping, you will get the following table DDL:If you choose to do an
Override<>
per subclass, you will have a linking table per subclass.就我而言,我想使用属性来指示应参与多对多关系的属性,其中仅声明关系的一侧。您可以轻松地修改它以按照其他约定进行映射。
多对多关系由
FluentNHibernate.Automapping.Steps.HasManyToManyStep
处理,这是DefaultAutomappingConfiguration
返回的IAutomappingStep
。仅当发现相关类型的相应属性时,此步骤才会映射属性(因此必须声明多对多关系的两端)。我采取的方法是:
HasManyToManyStep
创建一个装饰器类,该类支持根据属性(或其他约定)的存在来检测和映射多对多属性DefaultAutomappingConfiguration
到 自动映射并覆盖GetMappingSteps
,用装饰器包装HasManyToManyStep
的任何实例这是装饰器,它尝试使用默认的
首先具有ManyToManyStep
功能。否则,如果为成员定义了HasManyToManyAttribute
,它也将创建关系。用于创建关系的代码与HasManyToManyStep
- 只是不引用关系的另一方。HasManyToManyAttribute
类,因为在我的情况下没有其他约定可以轻松依赖:从
DefaultMappingConfiguration
类派生的配置类:In my case, I wanted to use an attribute to indicate a property that should participate in a many-to-many relationship where only one side of the relationship is declared. You could easily modify this to map by other conventions.
Many-to-many relationships are handled by
FluentNHibernate.Automapping.Steps.HasManyToManyStep
, anIAutomappingStep
returned by theDefaultAutomappingConfiguration
. This step will only map a property if it discovers a corresponding property of the related type (so both ends of the many-to-many relationship have to be declared).The approach I've taken is to:
HasManyToManyStep
that supports detecting and mapping many-to-many properties based on the presence of an attribute (or some other convention)DefaultAutomappingConfiguration
to when automapping and overrideGetMappingSteps
, wrapping any instance ofHasManyToManyStep
with the decoratorHere's the decorator, which tries to use the default
HasManyToManyStep
functionality first. Otherwise, ifHasManyToManyAttribute
is defined for the member, it will also create the relationship. The code used to create the relationship is nearly identical to the code used byHasManyToManyStep
- just without reference to the other side of the relationship.HasManyToManyAttribute
class, because there is no other convention I can easily rely on in my case:Configuration class derived from
DefaultMappingConfiguration
class: