简体   繁体   English

流利的NHibernate功能,用于更改袋子的钥匙栏

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM