对于子父的不同名称,正确的 Fluent NHibernate ConventionBuilder 是什么?也适用于棕地系统
这里需要什么代码:
,ConventionBuilder.HasMany.Always(x =>
x.Key.Column( /* what code need to go here? */ ))
除了使这个...
public virtual Person Owner { get; set; }
...到(这仅在绿地系统上是理想的):
public virtual Person Person { get; set; }
如何防止NHibernate在其DDL创建中产生无关的Person_id?
请注意 Person_id 是由 NH(或 FNH?)生成的,即使已经有一个owner_ref,并注意这两个引用:
create table contact (contact_id int4 not null,
number text, type text, owner_ref int4,
Person_id int4, primary key (contact_id));
create table person (person_id int4 not null, person_name text not null, birthdate timestamp not null, primary key (person_id));
alter table contact
add constraint FK38B7242018FA494F
foreign key (owner_ref) references person;
alter table contact
add constraint FK38B724202B329A0D
foreign key (Person_id) references person;
我尝试这样做只是为了确保防止无关引用是可行的
,ConventionBuilder.HasMany.Always(x => x.Key.Column("owner_ref"))
这是 NHibernate DDL 创建时我添加了 ConventionBuilder:
create table contact (contact_id int4 not null, number text, type text,
owner_ref int4, primary key (contact_id));
create table person (person_id int4 not null, person_name text not null, birthdate timestamp not null, primary key (person_id));
alter table contact
add constraint FK38B7242018FA494F
foreign key (owner_ref) references person;
注意不再有 Person_id 字段,并且现在只有一个引用,这是正确的。因此它可以防止重复引用,这是可能的,但我仍然不知道如何更改 ConventionBuilder 中 Person 下的集合的 KeyColumn 名称(IList
另一种方法是更改直接在ClassMap中的KeyColumn,防止联系人表中的重复引用......
HasMany(x => x.Contacts).Inverse().KeyColumn("owner_ref");
,实现了与上面相同的SQL,但如果我可以在ConventionBuilder上使其自动,那就更好了。
我如何告诉 NHibernate 生成两个引用?这是映射代码(请注意:public virtual Person Owner { get; set; }。它不是 Person Person { get; set; }
public class Person
{
public virtual int PersonId { get; set; }
public virtual string PersonName { get; set; }
public virtual DateTime Birthdate { get; set; }
public virtual IList<Contact> Contacts { get; set; }
}
public class Contact
{
public virtual Person Owner { get; set; }
public virtual int ContactId { get; set; }
public virtual string Number { get; set; }
public virtual string Type { get; set; }
}
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.PersonId);
Map(x => x.PersonName).Not.Nullable();
Map(x => x.Birthdate).Not.Nullable();
HasMany(x => x.Contacts).Inverse();
}
}
public class ContactMap : ClassMap<Contact>
{
public ContactMap()
{
References(x => x.Owner);
Id(x => x.ContactId).GeneratedBy.Sequence("contact_contact_id_seq");
Map(x => x.Number);
Map(x => x.Type);
}
}
该设计上正确的 ConventionBuilder 是什么模式(子表的字段引用父表的“_ref”后缀)。这也可能发生在棕地系统上。
What code need to go here:
,ConventionBuilder.HasMany.Always(x =>
x.Key.Column( /* what code need to go here? */ ))
Aside from making this...
public virtual Person Owner { get; set; }
...to(which is ideal only on greenfield systems):
public virtual Person Person { get; set; }
How can I prevent NHibernate from producing the extraneous Person_id in its DDL creation?
Note the Person_id was produced by NH(or FNH?) even there's already an owner_ref, and note the two references:
create table contact (contact_id int4 not null,
number text, type text, owner_ref int4,
Person_id int4, primary key (contact_id));
create table person (person_id int4 not null, person_name text not null, birthdate timestamp not null, primary key (person_id));
alter table contact
add constraint FK38B7242018FA494F
foreign key (owner_ref) references person;
alter table contact
add constraint FK38B724202B329A0D
foreign key (Person_id) references person;
I tried this just to make sure that it's feasible to prevent extraneous reference
,ConventionBuilder.HasMany.Always(x => x.Key.Column("owner_ref"))
Here's NHibernate DDL Creation when I add that ConventionBuilder:
create table contact (contact_id int4 not null, number text, type text,
owner_ref int4, primary key (contact_id));
create table person (person_id int4 not null, person_name text not null, birthdate timestamp not null, primary key (person_id));
alter table contact
add constraint FK38B7242018FA494F
foreign key (owner_ref) references person;
Note there are no more Person_id field, and there's only one references now, which is correct. So it prevent duplicate references, it's possible, but what I still doesn't know is how to change the KeyColumn's name of the collection(IList<Contact>) under Person in ConventionBuilder
Another way is to just change the KeyColumn in ClassMap directly, prevents duplicate reference in contact table...
HasMany(x => x.Contacts).Inverse().KeyColumn("owner_ref");
..., achieved the same SQL as above, but it's better if I can make it automatic on ConventionBuilder.
How can I tell NHibernate from producing two references? Here's the mapping code (note this: public virtual Person Owner { get; set; }. It's not Person Person { get; set; }
public class Person
{
public virtual int PersonId { get; set; }
public virtual string PersonName { get; set; }
public virtual DateTime Birthdate { get; set; }
public virtual IList<Contact> Contacts { get; set; }
}
public class Contact
{
public virtual Person Owner { get; set; }
public virtual int ContactId { get; set; }
public virtual string Number { get; set; }
public virtual string Type { get; set; }
}
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.PersonId);
Map(x => x.PersonName).Not.Nullable();
Map(x => x.Birthdate).Not.Nullable();
HasMany(x => x.Contacts).Inverse();
}
}
public class ContactMap : ClassMap<Contact>
{
public ContactMap()
{
References(x => x.Owner);
Id(x => x.ContactId).GeneratedBy.Sequence("contact_contact_id_seq");
Map(x => x.Number);
Map(x => x.Type);
}
}
What's the right ConventionBuilder on that design pattern("_ref" suffix for child table's field referencing parent table). That potentially happen on brownfield systems too.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你不能让它自动化。 NH 无法知道您想要对两个引用使用相同的外键。
编辑理论解决方案:
您需要以某种方式传递逆属性,因为这是缺失的部分。
我不知道如何实现它来获取此语法,但这基本上是您需要传递的信息。如果幸运的话,编译器可以从您正在映射的属性中获取类型(
Contact
)。理想情况下,你会得到这样的结果:
You can't make it automatic. NH can't know that you want to use the same foreign key for the two references.
EDIT theoretical solution:
You need to pass the inverse property somehow, because this is the missing part.
I don't know how to implement it to get this syntax, but this is basically the information you need to pass. If you are lucky you can obtain the Type (
Contact
) by the compiler from the property you are mapping.Ideally, you get it like this:
我已经找到(制定)了解决方案。关键是我们必须在实体的两端设置连接键,即我们必须在 ConventionBuilder.HasMany 和 ConventionBuilder.References 上设置它
ConventionBuilder .参考文献是一个已解决的问题。正是 ConventionBuilder.HasMany.Always(x =>) 我们需要想出一种从 .ConventionBuilder.HasMany.Always< 遍历引用对象(例如 Owner)的方法/strong> 代码。
我们必须根据 ConventionBuilder.HasMany 的多对一映射来标准化引用。不幸的是,references 属性处于受保护状态。 > 为此,我们必须扩展 ClassMap,并在我们的映射上使用该扩展类,以便我们可以遍历引用
以下是我编码的解决方案,在这里检查NormalizeReference的代码: http://www. ienablemuch.com/2010/12/brownfield-system-problem-on-fluence.html
I have found(formulated) the solution. The key thing is we must setup the joining key on both ends of the entities, i.e. we must set it up on ConventionBuilder.HasMany and ConventionBuilder.References
The ConventionBuilder.References is a solved problem. It is the ConventionBuilder.HasMany.Always(x => that we need to come up with a way of traversing the referencing object(e.g. Owner) from the .ConventionBuilder.HasMany.Always code.
We must normalize the references based on Many-To-One mappings from ConventionBuilder.HasMany. Unfortunately the references property is in protected access in ClassMap. For this, we must extend the ClassMap, and use that extended class on our mappings, so we can traverse the references
Following is the solution I coded, check the code of NormalizeReference here: http://www.ienablemuch.com/2010/12/brownfield-system-problem-on-fluent.html