流畅的NHibernate错误:实体’ClassMap`1’没有映射的Id

我正在将之前的项目从使用普通的NHibernate hbm.xml映射转换为Fluent NHibernate。 目前,我仍然坚持应该成为最后一步的工作之一。 我为DefaultAutomappingConfiguration添加了一个派生类来修改我的ID命名约定。 字符串“Id”附加到类名:

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

这应该使“代理商”在名为“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]]"} 

这是什么? 对象不是我创造的东西。 每个其他对象都通过这个函数很好,而我实际想要映射的对象返回正确的值。

我的Session工厂看起来像这样:

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

令人讨厌的是,似乎这在某种程度上导致了我在我的开发数据库中测试Fluent NHibernate的三个表被清空 。 我勒个去?

sessionfactory尝试根据此指令Add(AutoMap.AssemblyOf(cfg))包含您的Agency类的程序集中的所有类: Add(AutoMap.AssemblyOf(cfg)) 。 由于您在程序ClassMap<>有一个AgencyMapClassMap<>没有Id属性,因此FNH会抛出错误。

如果要使用ClassMap<>配置,而不是(或除此之外)声明自动化配置,请声明一个流畅的映射:

 m.FluentMappings.AddFromAssemblyOf(); 

如果您不需要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配置为使用配置/约定类:

  m.AutoMappings.AssemblyOf(new EntityAutoMappingConfiguration()) .IgnoreBase() .UseOverridesFromAssemblyOf() .Conventions.AddFromAssemblyOf(); 

您不能将ClassMap与automapper结合使用,除非您还将automapper配置为忽略您正在使用ClassMap的Entites及其各自的映射文件。

在我的情况下,我碰巧使用自定义属性来指示应该自动化的类,所以我可以抛出我不想映射到我的.dll的各种垃圾而不让Fluent尝试自动化它:

 ///  /// Add this attribute to entity classes which should be automapped by Fluent. ///  [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); } 

当然,如果只是将自动化实体保存在与其他类不同的命名空间中,则不需要检查属性。