Fluent NHibernate:外键违规或空值

发布于 2024-09-06 01:39:39 字数 2069 浏览 4 评论 0原文

大家好,我在使用 Fluent nhibernate 进行映射时遇到了一些实际问题。我意识到这个网站和其他许多网站上有很多帖子都专注于特定类型的映射,但到目前为止,我还没有找到解决我的问题的解决方案。

这是我所拥有的:

namespace MyProject.Models.Entites
{
    public class Project
    {
       public virtual Guid Id {get; set;}
       // A load of other properties
       public virtual ProjectCatagory Catagory{get;set;}           
    }
}

然后是地图:

namespace MyProject.DataAccess.ClassMappings
{
    public class ProjectMap : ClassMap<Project>
    {
        public ProjectMap()
        {
            Id(x => x.Id);
            Map(x => x.Title);
            Map(x => x.Description);
            Map(x => x.LastUpdated);
            Map(x => x.ImageData).CustomSqlType("image");
            HasOne(x => x.Catagory);           
        }
    }
}

正如您所看到的,我有一个包含类别属性的项目。我对关系数据库不太热衷,但据我所知,这是一种多一关系,其中许多项目可以有一个类别。不,项目不能属于多个类别。

现在我们有了:

namespace MyProject.Models.Entities
{
   public class ProjectCatagory
   {
        public virtual Guid Id { get; set; }
        public virtual String Name { get; set; }
   }
}

及其地图:

public ProjectCatagoryMap()
{
    Id(x => x.Id);
    Map(x => x.Name);
}

问题是,它不起作用!我将在单元测试中执行类似于以下操作的操作:

Project myproject = new Project("Project Description");
// set the other properties
myProject.Catagory = new ProjectCatagory(Guid.New(), "Test Catagory");
repository.Save(myProject);

现在,在尝试使其正常工作时,我尝试了许多映射和数据库配置。目前,项目数据库表有一列“Catagory_id”(我没有放在那里,我假设 NH 作为映射的结果添加了它),我希望将其设置为不允许空值。但是,当这样设置时,我会收到异常,解释说我无法将空值插入表中(即使在调试期间,我已经检查了 Project 对象上的所有属性,并且它们不为空)。

或者,我可以允许表在该列中接受空值,它只会保存项目对象,并在保存时完全忽略类别属性,因此,在检索时,测试检查正确的类别是否与项目关联失败。

如果我没记错的话,在某一时刻我使用了 ProjectMap:

References(x => x.Catagory).Column("Catagory_id").Cascade.All().Not.Nullable();

这将异常从“无法插入空值”更改为外键违规。

我怀疑所有这些麻烦的根源都来自于我对关系数据库设置缺乏了解,因为我在这个项目中还有其他实体,它们没有外部依赖项,它们与 NHibernate 一起工作绝对正常,排除了我可能引起的任何编码问题创建存储库。

非常感谢任何帮助。谢谢。

Hey guys, I am having some real issues with mapping using fluent nhibernate. I realise there are MANY posts both on this site and many others focusing on specific types of mapping but as of yet, I have not found a solution that solves my issue.

Here is what I have:

namespace MyProject.Models.Entites
{
    public class Project
    {
       public virtual Guid Id {get; set;}
       // A load of other properties
       public virtual ProjectCatagory Catagory{get;set;}           
    }
}

and then the map:

namespace MyProject.DataAccess.ClassMappings
{
    public class ProjectMap : ClassMap<Project>
    {
        public ProjectMap()
        {
            Id(x => x.Id);
            Map(x => x.Title);
            Map(x => x.Description);
            Map(x => x.LastUpdated);
            Map(x => x.ImageData).CustomSqlType("image");
            HasOne(x => x.Catagory);           
        }
    }
}

So as you can see, I have a project which contains a catagory property. Im not so hot on relational databases but from what I can figure, this is a many-one relationship where many Projects can have one catagory. No, projects cannot fall into more than one category.

So now we have:

namespace MyProject.Models.Entities
{
   public class ProjectCatagory
   {
        public virtual Guid Id { get; set; }
        public virtual String Name { get; set; }
   }
}

and its map:

public ProjectCatagoryMap()
{
    Id(x => x.Id);
    Map(x => x.Name);
}

Issue is, well, it doesn't work ! I will do something similar to the following in a unit test:

Project myproject = new Project("Project Description");
// set the other properties
myProject.Catagory = new ProjectCatagory(Guid.New(), "Test Catagory");
repository.Save(myProject);

Now I have tried a number of mapping and database configurations when trying to get this to work. Currently, the Project database table has a column, "Catagory_id" (which i didnt put there, i assume NH added it as a result of the mapping) and I would LIKE it set to not allow nulls. However, when set as such, I get exceptions explaining that I cannot insert null values into the table (even though during a debug, i have checked all the properties on the Project object and they are NOT null).

Alternatively, I can allow the table to accept nulls into that column and it will simply save the Project object and totally disregard the Category property when saving, therefore, when being retrieved, tests to check if the right category has been associated with the project fails.

If i remember correctly, at one point I had the ProjectMap use:

References(x => x.Catagory).Column("Catagory_id").Cascade.All().Not.Nullable();

this changed the exception from "Cannot insert null values" to a foreign key violation.

I suspect the root of all this hassle comes from my lack of understanding of relational database set up as I have other entities in this project that do not have external dependencies which work absolutely fine with NHibernate, ruling out any coding issues I may of caused when creating the repository.

Any help greatly appreciated. Thank you.

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

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

发布评论

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

评论(3

陈年往事 2024-09-13 01:39:39

这里的主要问题是对关系数据库中的“一对一”关系和 Fluent 中的 HasOne 映射的常见误解。映射中的术语是关系术语。 (Fluent 试图“美化”它们一点,这在我看来使情况变得更糟。HasOne 实际上意味着:一对一。)

看看 Fluent wiki

HasOne 通常保留给
特例。一般来说,你会使用
大多数情况下的参考关系
情况(参见:我认为你的意思是
多对一)。

解决方案很简单,只需将 HasOneReferences 交换(一对一多对一 > 在 XML 映射文件中)。您在数据库中获得一个引用 ProjectCatagory 的外键。


关系数据库中真正的一对一关系理想地通过主键同步来映射。当两个对象共享相同的主键时,您就不会浪费额外的外键空间,并且可以确保它是一对一的。

要同步主键,您需要将一个密钥连接到其他密钥。然而这可行,但这不是您所需要的。

The main issue here is a common misunderstand about the "one-to-one" relation in a relational database and the HasOne mapping in Fluent. The terms in the mapping are relational terms. (Fluent tries to "beautify" them a bit which makes it worse IMO. HasOne actually means: one-to-one.)

Take a look at the Fluent wiki:

HasOne is usually reserved for a
special case. Generally, you'd use a
References relationship in most
situations (see: I think you mean a
many-to-one).

The solution is very simple, just exchange HasOne with References (one-to-one to many-to-one in an XML mapping file). You get a foreign key in the database which references the ProjectCatagory.


A real one-to-one relation in a relational database is ideally mapped by a primary key synchronization. When two objects share the same primary key, then you don't waste space for additional foreign keys and it is ensured to be one-to-one.

To synchronize primary key, you need to hook up one's key to the others. However this works, it is not what you need here.

2024-09-13 01:39:39

在尝试了所有可用的映射选项之后。我发现答案与建议的类似。

正如所怀疑的那样,HasOne() 显然是错误的,而 References(x => x.Catagory) 是解决方案的一部分。但是,我仍然收到外键违规异常,直到:

References(x => x.Catagory).Column("Catagory_id").Cascade.SaveUpdate().Not.Nullable().Not.LazyLoad();

只是认为 id 会更新线程,以防其他人偶然发现类似的问题,因为仅使用 References() 不起作用。

After playing around with all the available options for mapping. I found the answer to be similar to that suggested.

As was suspected, HasOne() was clearly wrong and References(x => x.Catagory) was part of the solution. However, I still received foreign key violation exceptions until:

References(x => x.Catagory).Column("Catagory_id").Cascade.SaveUpdate().Not.Nullable().Not.LazyLoad();

Just thought id update the thread in case someone else stumbles across this with a similar issue as just using References() did not work.

空城旧梦 2024-09-13 01:39:39

看来 ProjectCatagory 类是 Project 类的父类。那么没有父类怎么可能有子类呢。

您必须使用 -

References(x => x.Catagory).Column("Catagory_id").Foreignkey("Id");

这里的外键是您的 ProjectCatagory 表 ID。

Its seems ProjectCatagory class is parent class of Project Class. So without parent class how can child class exist.

You have to use -

References(x => x.Catagory).Column("Catagory_id").Foreignkey("Id");

here Foreign Key is your ProjectCatagory table ID.

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