2011-07-11 53 views
4

我正在轉換使用正常的NHibernate hbm.xml映射到流利NHibernate以前的項目。目前,我被困在應該是實現這個工作的最後步驟之一。我已經爲DefaultAutomappingConfiguration添加了派生類來修改我的ID命名約定。字符串「Id」附加到類名稱上:流利NHibernate的錯誤:實體的'ClassMap`1'沒有一個Id映射

public override bool IsId(FluentNHibernate.Member member) 
    { 
     return member.Name == member.DeclaringType.Name + "Id"; 
    } 

這應該使「Agency」在名爲「AgencyId」的字段中有一個ID。相反,我得到這個錯誤:

The entity 'ClassMap`1' doesn't have an Id mapped. Use the Id method to map your identity property. For example: Id(x => x.Id). 
{Name = "ClassMap`1" FullName = "FluentNHibernate.Mapping.ClassMap`1[[BackendDb.Model.Agency, BackendDb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"} 

我做的ISID功能斷點,看看發生了什麼事情:

{Property: Cache} 
{Name = "ClassMap`1" FullName = "FluentNHibernate.Mapping.ClassMap`1[[BackendDb.Model.Agency, BackendDb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"} 

這是什麼?該對象不是我創建的。其他每個對象都可以很好地通過這個函數,而我實際想要映射的那些對象會返回正確的值。

我的會話工廠看起來是這樣的:

var cfg = new MapConfig(); 
return Fluently.Configure() 
.Database(MsSqlConfiguration.MsSql2008 
.ConnectionString(m => m.Server(@".\SqlExpress") 
    .Database("{some dbname}") 
    .TrustedConnection())) 
.Mappings(m => 
    m.AutoMappings 
     .Add(AutoMap.AssemblyOf<Agency>(cfg)) 
) 
.BuildSessionFactory(); 

煩人,似乎這在某種程度上造成了三個表我是在我的開發數據庫測試功能NHibernate是清空。我勒個去?

+1

是你的'Agency'類實現或擴展ClassMap嗎?除非您使用映射文件,否則您不應該引用它。 –

+0

是:public class代理地圖:ClassMap Chris

回答

7

sessionfactory試圖根據此指令自動映射包含Agency類的程序集中的所有類:Add(AutoMap.AssemblyOf<Agency>(cfg))。由於在程序集中有一個AgencyMap,並且ClassMap<>沒有Id屬性,FNH會引發錯誤。

如果你想使用ClassMap<>配置,而不是(或除了)聲明的自動映射配置,聲明說一口流利的映射:

m.FluentMappings.AddFromAssemblyOf<Agency>(); 

如果您不需要AutoMappings,刪除`.AutoMappings .Add'指令。

但是,如果您想使用AutoMappings,則需要告訴FNH您要映射哪些類。爲了解決這個問題,我通常會定義一個標記接口:

public abstract class Entity : IPersistable 
{ 
    public virtual int Id { get; set; } 
} 

public interface IPersistable 
{ 
} 

然後,在我從DefaultAutomappingConfiguration派生類,我告訴FNH僅映射有該接口的類(你可以限制映射類,但是你認爲合適):

public class EntityAutoMappingConfiguration : DefaultAutomappingConfiguration 
{ 
    public override bool ShouldMap(Type type) 
    { 
     return type.GetInterfaces().Contains(typeof (IPersistable)); 
    } 

} 

要處理的主鍵映射,我創建了一個約定類:

public class PrimaryKeyNamePlusId : IIdConvention 
{ 
    public void Apply(IIdentityInstance instance) 
    { 
     instance.Column(instance.EntityType.Name+"Id"); 
    } 
} 

最後,配置我的SessionFactory使用CONFI guration/convention classes:

m.AutoMappings.AssemblyOf<Entity>(new EntityAutoMappingConfiguration()) 
      .IgnoreBase<Entity>() 
      .UseOverridesFromAssemblyOf<Entity>() 
      .Conventions.AddFromAssemblyOf<Entity>(); 
+0

將自動映射更改爲m.FluentMappings.AddFromAssemblyOf ();似乎工作。我要用一些額外的實體來測試它,而不是僅僅那個。 – Chris

+0

這應該可以正常工作。如果你不想,你不需要做自動映射。但是,使用automapping +慣例可以爲您節省大量時間。看看這個帖子,如果你有興趣:http://iamnotmyself.com/2011/06/22/using-fluent-nhibernate-classmaps-youre-doing-it-wrong/ – codeprogression

+0

我正在工作我的方式到這些的東西。使用流利NHibernate是我第一次實現NHibernate時推遲做的事情(它已經夠難了),所以我會在稍後保存它。除非它非常微不足道,否則我現在就去做。我使用的是舊數據庫,因此我現在不想真正設置所有的約定。 – Chris

0

您不能將ClassMap與自動映射器結合使用,除非您還將自動映射器配置爲忽略您正在使用ClassMap及其各自映射文件的Entites。

就我而言,我碰巧使用自定義屬性來指示被automapped類,所以我能折騰各種垃圾,我不想被映射到我的.dll文件,而無需流利嘗試自動映射它:

/// <summary> 
/// Add this attribute to entity classes which should be automapped by Fluent. 
/// </summary> 
[AttributeUsage(AttributeTargets.Class)] 
class AutomapAttribute : Attribute 
{ 
} 

在我DefaultAutomappingConfiguration覆蓋類:

public override bool ShouldMap(Type type) 
    { 
     return (type.Namespace == "Data.Entities" 
      && type.GetCustomAttributes(typeof(AutomapAttribute), false).Length > 0); 
    } 

當然,你並不需要檢查的屬性,如果你只是保持你的automapped實體從其他類不同的命名空間。

+0

我已經嘗試覆蓋應用地圖,但不是那樣。 – Chris