Fluent NHibernate 错误:实体“ClassMap`1”没有映射的 ID

发布于 2024-11-19 12:01:58 字数 1452 浏览 2 评论 0原文

我正在将以前的项目从使用普通 NHibernate hbm.xml 映射转换为 Fluent NHibernate。目前,我陷入了让这项工作发挥作用的最后步骤之一。我为 DefaultAutomappingConfiguration 添加了一个派生类来修改我的 ID 命名约定。字符串“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();

令人烦恼的是,这似乎以某种方式导致我在开发数据库中测试 Fluent NHibernate 的三个表被清空。我勒个去?

I'm converting a previous project from using normal NHibernate hbm.xml mappings to Fluent NHibernate. Currently, I'm stuck on what should be one of the last steps to getting this working. I've added a derived class for DefaultAutomappingConfiguration to modify my ID naming convention. The string "Id" is appended to the class name:

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

This should make "Agency" have an ID in a field named "AgencyId". Instead, I'm getting this error:

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

I made a breakpoint on the IsId function to see what's going on:

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

What is this? The object is not something I've created. Every other object passes through this function fine, and the ones I actually wanted to map are returning the proper value.

My Session factory looks something like this:

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

Annoyingly, it seems that this somehow caused the three tables I was testing Fluent NHibernate on in my dev database to be emptied. What the hell?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏至、离别 2024-11-26 12:01:58

sessionfactory 尝试根据以下指令自动映射包含 Agency 类的程序集中的所有类:Add(AutoMap.AssemblyOf(cfg))。由于程序集中有一个 AgencyMap,而 ClassMap 没有 Id 属性,因此 FNH 会引发错误。

如果您想使用 ClassMap 配置,而不是(或除了)声明自动映射配置之外,请声明一个流畅的映射:

m.FluentMappings.AddFromAssemblyOf<Agency>();

如果您不需要 AutoMappings,请删除`.AutoMappings。添加'指令。

但是,如果您想使用 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<Entity>(new EntityAutoMappingConfiguration())
            .IgnoreBase<Entity>()
            .UseOverridesFromAssemblyOf<Entity>()
            .Conventions.AddFromAssemblyOf<Entity>();

The sessionfactory is trying to automap all classes in the assembly that contains your Agency class based on this directive: Add(AutoMap.AssemblyOf<Agency>(cfg)). Since you have an AgencyMap in the assembly andClassMap<> does not have an Id property, FNH is throwing an error.

If you want to use ClassMap<> configurations, instead of (or in addition to) declaring an automapping configuration, declare a fluent mapping:

m.FluentMappings.AddFromAssemblyOf<Agency>();

If you don't need AutoMappings, remove the `.AutoMappings.Add' directive.

However, if you want to use AutoMappings, you need to tell FNH what classes you want to map. To handle this, I usually define a marker interface:

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

public interface IPersistable
{
}

Then, in the class that I derive from DefaultAutomappingConfiguration, I tell FNH to only map the classes that have that interface (you can limit the mapped classes however you see fit):

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

}

To handle the primary key mapping, I create a convention class:

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

Finally, I configure my SessionFactory to use the configuration/convention classes:

 m.AutoMappings.AssemblyOf<Entity>(new EntityAutoMappingConfiguration())
            .IgnoreBase<Entity>()
            .UseOverridesFromAssemblyOf<Entity>()
            .Conventions.AddFromAssemblyOf<Entity>();
逐鹿 2024-11-26 12:01:58

您不能将 ClassMap 与自动映射器结合使用,除非您还配置自动映射器以忽略您正在使用 ClassMap 的实体及其各自的映射文件。

就我而言,我碰巧使用自定义属性来指示应该自动映射的类,因此我可以将我不想映射到 .dll 中的各种垃圾扔掉,而无需 Fluent 尝试自动映射it:

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

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

You can't use ClassMap in combination with the automapper unless you also configure the automapper to ignore the Entites for which you are using ClassMap and their respective mapping files.

In my case, I happen to use a custom attribute to indicate classes which should be automapped, so I can toss all sorts of garbage I don't want mapped into my .dll without having Fluent try to automap it:

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

And in my DefaultAutomappingConfiguration override class:

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

Of course, you don't need to check for an attribute if you just keep your automapped entities in a different namespace from other classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文