2012-11-26 51 views
3

我有這種複雜的情況:一個國家/地區/國家/城市的數據庫主鍵是由一個名爲「Id」的列中的代碼(nvarchar(3))組成的, 「祖先」(地區/州/城市)列。流利的NHibernate自動映射組合ID與組件

所以表格國家只有一個關鍵coumn(Id),而城市有4個關鍵列(Id,StateId,regionId,CountryId)。顯然它們都是相關的,所以每個祖先列都是相關表的外鍵。

我有我的模型中的實體映射這種關係。但它們都來自一種稱爲Entity <T>的類型,其中T可以是簡單類型(字符串,等等)或複雜類型(實現密鑰的組件)。 實體<Ť>實現名爲ID類型T.

的各個DB表中的單個屬性,如果它有一個COMLEX鍵,我實現它在一個單獨的部件,其oveerides也等於和GetHashCode()方法(在未來我將在實體基類中實現這些)。

所以我有一個RegionKey組件具有2個屬性(Id和CountryId)。 我有外鍵和主鍵命名和類型的約定,這是好的。 我也爲每個複雜的實體映射ovverrides。

爲了簡單起見,我們只關注國家和地區表。它們是:

public class Country: Entity<string> 
{ 
    public virtual string Name { get; set; } 
    public virtual IList<Region> Regions { get; set; } 
} 

public class Region: Entity<RegionKey> 
{ 
    public virtual string Name { get; set; } 
    public virtual Country Country { get; set; } 
} 

和RegionKey組分:

namespace Hell.RealHellState.Api.Entities.Keys 
{ 
    [Serializable] 
    public class RegionKey 
    { 
    public virtual string Id { get; set; } 
    public virtual string CountryId { get; set; } 

    public override bool Equals(object obj) 
    { 
     if (obj == null) 
      return false; 
     var t = obj as RegionKey; 
     if (t == null) 
      return false; 
     return Id == t.Id && CountryId == t.CountryId; 
    } 

    public override int GetHashCode() 
    { 
     return (Id + "|" + CountryId).GetHashCode(); 
    } 
    } 
} 

這裏是AutoPersistenceModel的配置:

public ISessionFactory CreateSessionFactory() 
    { 
     return Fluently.Configure() 
      .Database(
      MsSqlCeConfiguration.Standard 
      .ConnectionString(x=>x.Is(_connectionString)) 
     ) 
      .Mappings(m => m.AutoMappings.Add(AutoMappings)) 
      .ExposeConfiguration(BuildSchema) 
      .BuildSessionFactory(); 
    } 

    private AutoPersistenceModel AutoMappings() 
    { 
     return AutoMap.Assembly(typeof (Country).Assembly) 
      .IgnoreBase(typeof(Entity<>)) 
      .Conventions.AddFromAssemblyOf<DataFacility>() 
      .UseOverridesFromAssembly(GetType().Assembly) 
      .Where(type => type.Namespace.EndsWith("Entities")); 
    } 

    private static void BuildSchema(Configuration config) 
    { 
     //Creates database structure 
     new SchemaExport(config).Create(false, true); 
     //new SchemaUpdate(config).Execute(false, true); 
    } 

這裏是地區實體覆蓋

public class RegionMappingOverride : IAutoMappingOverride<Region> 
{ 
    public void Override(AutoMapping<Region> mapping) 
    { 
     mapping.CompositeId(x=>x.Id) 
      .KeyProperty(x => x.Id, x=> x.ColumnName("Id").Length(3).Type(typeof(string))) 
      .KeyProperty(x => x.CountryId, x => x.ColumnName("CountryId").Length(3).Type(typeof(string))); 
    } 
} 

現在可以當我測試這個映射時,我得到一個錯誤:關係中列的數據類型不匹配。

我自己也嘗試這種覆蓋:

public void Override(AutoMapping<Region> mapping) 
    { 
     mapping.CompositeId() 
      .ComponentCompositeIdentifier(x=>x.Id) 
      .KeyProperty(x => x.Id.Id, x=> x.ColumnName("Id").Length(3).Type(typeof(string))) 
      .KeyProperty(x => x.Id.CountryId, x => x.ColumnName("CountryId").Length(3).Type(typeof(string))); 
    } 

它幾乎工作,但它與VARBINARY(8000)中的一列鍵創建一個區域表這是不是我想要的:

CREATE TABLE [hell_Regions] (
[Id] varbinary(8000) NOT NULL 
, [Name] nvarchar(50) NULL 
, [CountryId] nvarchar(3) NULL 
); 
GO 
ALTER TABLE [hell_Regions] ADD CONSTRAINT [PK__hell_Regions__0000000000000153] PRIMARY KEY ([Id]); 
GO 
ALTER TABLE [hell_Regions] ADD CONSTRAINT [FK_Regions_Country] FOREIGN KEY ([CountryId]) REFERENCES [hell_Countries]([Id]) ON DELETE NO ACTION ON UPDATE NO ACTION; 
GO 

我不知道如何處理它,因爲在我看來,每件事情都可以。

預先感謝您的回答

回答

4

好,我menaged解決這個問題:我有籤CompositeId類作爲映射的,因爲它是一個組件。所以這是我的新RegionMappingOverride:

public class RegionMappingOverride : IAutoMappingOverride<Region> 
{ 
    public void Override(AutoMapping<Region> mapping) 
    { 
     mapping.CompositeId(x=>x.Id) 
      .Mapped() 
      .KeyProperty(x =>x.Id,x=>x.Length(3)) 
      .KeyProperty(x => x.CountryId, x=>x.Length(3)); 
    } 

} 

現在創建的SQL是正確的:

create table hell_Countries (
    Id NVARCHAR(3) not null, 
    Name NVARCHAR(50) null, 
    primary key (Id) 
) 

create table hell_Regions (
    Id NVARCHAR(3) not null, 
    CountryId NVARCHAR(3) not null, 
    Name NVARCHAR(50) null, 
    primary key (Id, CountryId) 
) 

alter table hell_Regions 
    add constraint FK_Region_Country 
    foreign key (CountryId) 
    references hell_Countries