2010-12-07 10 views
0

<キー列= "Person_id"/> Fluent NHibernateでの対応は?私はhasManyのコンタクトを変更しようとしているFluent NHibernate関数でバッグのキー列を変更する

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 
); 

:私はこの2つのテーブルを持っている

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; } 
} 

<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]

私はこのマッピングを持っています'キー列からyyyy、Fluent NHibernateのデフォルトはPerson_idです。 ConventionBuildersは私のプログラムの問題のケースにベアリングを持っていることを万が一

た場合(資本PERSON_IDのPを(私は)流暢すぎ大会オーバーの設定をしていると思います注意してください)、ここではどのように私のセットアップ私の表記です:

そして、このコード

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(); 
    }    
} 
...

foreach(Contact c in p.Contacts) // p doesn't have problems. Iterating its Contacts has 
{ 
    Console.WriteLine("Contact: {0} {1}", c.Number, c.Type); 
} 

...生成:

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 
+0

あなたは「この変更はどういう意味ですか流暢な "を通して? – Phill

+0

私はFluent NHibernateを学んでいる "FluentTry"とあなたのマッピングによって推測します。私は人の単純なマッピング、表記法などの基本的なものを試してみるべきだと思います。 – Phill

+0

こんにちはPhill、助けになるなら私はFNHコード –

答えて

1

私は今それを解決しました(良いことはFluent NHibernateはopensourceです)。私はキーマッピングコレクションをクリアし、再度追加することを計画し

keyMapping.AddDefaultColumn(new ColumnMapping { Name = entity.Name + "_id" }); 

:人のhasManyのはにToManyBase.cs(FNHのソースコードで)、デフォルトで見つかったキーマッピングコレクションからその外部キー列名を生成し、私のカスタマイズされたキー列名(「YYYY」)が、私はする必要はありません良いこと、FNHはすでに(OneToManyPart.csで)場合、KeyColumn機能をその機能を持っている、これはその定義です:

public OneToManyPart<TChild> KeyColumn(string columnName) 
    { 
     Key(ke => 
     { 
      ke.Columns.Clear(); 
      ke.Columns.Add(columnName); 
     }); 
     return this; 
    } 

ので、外部キーのフィールド名がClassName + "_id"の形式でない場合は、 から.Column(yourCustomizedFieldNameHere)がルートクラス 'collections'にあります。参考資料 ContactMap)...

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 

...あなたも、すなわち、あなたのルートクラスであなたの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 
関連する問題