[英]Fluent NHibernate function for changing bag's key column
What's the equivalent of <key column="Person_id"/> in Fluent NHibernate?? 与Fluent NHibernate中的<key column =“ Person_id” />等效吗?
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="FluentTry.Person, FluentTry, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="person">
<id name="PersonId" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="person_id" />
<generator class="identity" />
</id>
<bag inverse="true" name="Contacts" mutable="true">
<key>
<column name="Person_id" /> <!-- how to change this through Fluent? -->
</key>
</bag>
[EDIT] [编辑]
I have this mapping: 我有这个映射:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.PersonId);
Map(x => x.PersonName).Not.Nullable();
Map(x => x.Birthdate).Not.Nullable();
Component(x => x.Birthplace).ColumnPrefix("birthplace_");
HasMany(x => x.Contacts).Inverse();
}
}//PersonMap
public class ContactMap : ClassMap<Contact>
{
public ContactMap()
{
References(x => x.Owner).Column("yyyy");
Id(x => x.ContactId).GeneratedBy.Sequence("contact_contact_id_seq");
Map(x => x.Number);
Map(x => x.Type);
}
}//ContactMap
public class AddressComponentMap : ComponentMap<AddressComponent>
{
public AddressComponentMap()
{
// ConventionBuilder.Property.Always doesn't have an effect on Column method of Map of ComponentMap. We need to override it by ourselves
Map(x => x.StreetNumber).Column("street_number");
Map(x => x.Street).Column("street");
Map(x => x.City).Column("city");
Map(x => x.PostCode).Column("post_code");
}
}//AddressComponentMap
// POCOs...
public class Person
{
public virtual int PersonId { get; set; }
public virtual string PersonName { get; set; }
public virtual DateTime Birthdate { get; set; }
public virtual AddressComponent Birthplace { get; set; }
public virtual IList<Contact> Contacts { get; set; }
}
public class AddressComponent
{
public virtual string StreetNumber { get; set; }
public virtual string Street { get; set; }
public virtual string City { get; set; }
public virtual string PostCode { 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; }
}
I have this two tables: 我有这两个表:
CREATE TABLE person
(
person_id serial NOT NULL PRIMARY KEY,
person_name text NOT NULL,
birthdate date NOT NULL,
birthplace_street_number text NOT NULL,
birthplace_street text NOT NULL,
birthplace_city text NOT NULL,
birthplace_post_code text NOT NULL
);
create table contact
(
yyyy int not null references person(person_id),
contact_id serial not null primary key,
number text not null,
type text not null
);
I'm trying to change the HasMany Contacts' key column to yyyy, Fluent NHibernate defaults to Person_id. 我试图将HasMany Contacts的键列更改为yyyy,Fluent NHibernate默认为Person_id。 (Note the capital P of Person_id (I think Fluent is having too much convention-over-configuration) )
(请注意,Person_id的大写字母P(我认为Fluent在配置中约定过多))
If by any chance that ConventionBuilders have bearing on my program's problem case, here's how I setup my Conventions: 如果ConventionBuilders可能会影响我程序的问题情况,请按照以下步骤设置我的Conventions:
static ISessionFactory CreateSessionFactory()
{
return (ISessionFactory) Fluently.Configure()
.Database
(
PostgreSQLConfiguration.Standard.ConnectionString("Server=localhost;Database=fluent_try;User ID=postgres;Password=opensesame;")
)
.Mappings( m => m.FluentMappings.AddFromAssemblyOf<MainClass>()
.Conventions.Add(
ConventionBuilder.Class.Always( x => x.Table( x.EntityType.Name.ToPostgresNamingConvention() ) )
,ConventionBuilder.Property.Always( x => x.Column(x.Name.ToPostgresNamingConvention() ) )
,ConventionBuilder.Id.Always( x => x.Column(x.Name.ToPostgresNamingConvention() ) )
)
.ExportTo("/Users/Michael")
)
.BuildSessionFactory();
}
public static class Helper
{
public static string ToPostgresNamingConvention(this string s)
{
var r = new Regex(@"
(?<=[A-Z])(?=[A-Z][a-z]) |
(?<=[^A-Z])(?=[A-Z]) |
(?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace);
return r.Replace(s, "_").ToLower();
}
}
And this code... 这段代码
foreach(Contact c in p.Contacts) // p doesn't have problems. Iterating its Contacts has
{
Console.WriteLine("Contact: {0} {1}", c.Number, c.Type);
}
...produces: ...产生:
Unhandled Exception: NHibernate.Exceptions.GenericADOException:
could not initialize a collection: [FluentTry.Person.Contacts#1][SQL: SELECT
contacts0_.Person_id as Person5_1_, contacts0_.contact_id as contact1_1_,
contacts0_.contact_id as contact1_0_0_, contacts0_.number as number0_0_, contacts0_.type
as type0_0_, contacts0_.yyyy as yyyy0_0_ FROM contact contacts0_ WHERE
contacts0_.Person_id=?] ---> Npgsql.NpgsqlException:
column contacts0_.person_id does not exist
Severity: ERROR
Code: 42703
I solved it now (good thing Fluent NHibernate is opensource). 我现在解决了(Fluent NHibernate是开源的)。 Person's HasMany generates its foreign key column name from keyMapping collection , found in ToManyBase.cs (in FNH's source code), it defaults to:
Person的HasMany通过在ToManyBase.cs中找到的keyMapping集合 (在FNH的源代码中)生成其外键列名称,默认为:
keyMapping.AddDefaultColumn(new ColumnMapping { Name = entity.Name + "_id" });
I plan to clear the keyMapping collection and re-add my customized key column name("yyyy"), but good thing I don't need to, FNH already has that function, KeyColumn function(in OneToManyPart.cs), this is its definition: 我打算清除keyMapping集合并重新添加我自定义的键列名称(“ yyyy”),但是我不需要的是,FNH已经具有该功能KeyColumn函数(在OneToManyPart.cs中),这就是它的定义:
public OneToManyPart<TChild> KeyColumn(string columnName)
{
Key(ke =>
{
ke.Columns.Clear();
ke.Columns.Add(columnName);
});
return this;
}
So, if your foreign key's fieldname is not in the form of ClassName + "_id", aside from adding .Column(yourCustomizedFieldNameHere) in your root class' collections' References (eg ContactMap)... 因此,如果您的外键的字段名不是ClassName +“ _id”的形式,除了在根类的集合的引用 (例如ContactMap)中添加.Column(yourCustomizedFieldNameHere )...
public class ContactMap : ClassMap<Contact>
{
public ContactMap()
{
References(x => x.Owner).Column("yyyy"); // must add .Column if your fieldname is not of Classaname + "_id" form
Id(x => x.ContactId);
Map(x => x.Number);
Map(x => x.Type);
}
}//ContactMap
...you must also add .KeyColumn(yourCustomizedFieldNameHere) to your HasMany mapping in your root class, ie: ...您还必须在根类的HasMany映射中添加.KeyColumn(yourCustomizedFieldNameHere) ,即:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.PersonId);
Map(x => x.PersonName).Not.Nullable();
Map(x => x.Birthdate).Not.Nullable();
Component(x => x.Birthplace).ColumnPrefix("birthplace_");
HasMany(x => x.Contacts).KeyColumn("yyyy").Inverse(); // must add .KeyColumn
}
}//PersonMap
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.