2010-12-07 4 views
0

Was entspricht < Schlüssel Spalte = "Person_id"/> in fließenden NHibernate ??Flüssige NHibernate-Funktion zum Ändern der Tasche Schlüssel Spalte

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

Ich habe diese Abbildung:

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

Ich habe diese zwei Tabellen:

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

Ich versuche, die HasMany Kontakte zu ändern 'Schlüsselspalte bis JJJJ, Fluent NHibernate ist standardmäßig Person_id. (Beachten Sie die Hauptstadt P von person_id (ich glaube, fliessend zu viel convention-over-Konfiguration ist mit))

Wird durch Zufall, dass ConventionBuilders haben Einfluss auf mein Programm der Problemfall, hier ist, wie ich mein Setup Konventionen:

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

Und dieser 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); 
} 

... produziert:

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

Was meinst du mit „verändern fließend "? – Phill

+0

Ich gehe davon aus, dass Sie mit FluentTry Fluent NHibernate lernen. Ich denke, dass Sie etwas Grundlegendes versuchen sollten, wie eine einfache Zuordnung der Person, keine Konventionen, richten Sie einfach die Konfiguration ein, um die Tabellen für Sie zu erstellen, damit Sie sehen können, was es produziert. – Phill

+0

Hallo Phill, wenn es helfen würde, habe ich meinen FNH-Code –

Antwort

1

Ich habe es jetzt gelöst (gute Sache Fluent NHibernate ist opensource). Person HasMany generiert seine Fremdschlüsselspaltennamen aus Keymapping Sammlung, gefunden in ToManyBase.cs (in FNH Quellcode), wird standardmäßig:

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

Ich plane, die Keymapping Sammlung zu löschen und erneut hinzufügen mein personalisiertem Schlüssel Spaltenname ("yyyy"), aber gut, was ich brauche nicht zu, FNH hat bereits diese Funktion, KeyColumn Funktion (in OneToManyPart.cs), das ist seine Definition:

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

So, wenn der Feldname Ihres Fremdschlüssels nicht in der Form ClassName + "_id" steht von hinzufügen. Spalte (yourCustomizedFieldNameHere) in Ihrer Root-Klasse 'Sammlungen' Referenzen (z. 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 

... Sie auch .KeyColumn (yourCustomizedFieldNameHere) auf Ihre HasMany Mapping in der Stammklasse, also müssen hinzufügen:

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