映射nhibernate父/子关系的'其他'方式

时间:2012-02-02 07:08:53

标签: c# nhibernate fluent-nhibernate

使用FluentNhibernate;

我试图坚持一个看似简单的对象模型:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Config Config { get; set; }
}

public class Config
{
    public int ConfigId { get; set; }
    public int ProductId { get; set; }
    public string ConfigField1 { get; set; }
    public string ConfigField2 { get; set; }
}

并且数据库看起来像:(在语法上不正确)

CREATE TABLE [dbo].[Products](
[ProductId] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL
)

CREATE TABLE [dbo].[Config](
[ConfigId] [int] IDENTITY(1,1) NOT NULL,
[ProductId] [int] NOT NULL,
[ConfigField1] [varchar](50) NULL,
[ConfigField2] [varchar](50) NULL
) ON [PRIMARY]

开箱即用的fluent-nhibernate将尝试将其映射为Products表上的外键,例如:

  

INSERT INTO Products(Name,Config_id)VALUES(?,?);

我不希望它这样做,而是我希望映射会首先插入Products,然后将第ProductId插入Config表中的第二个配置。

我拔掉头发试图覆盖并阅读thisthis之类的链接,但仍然无法让它按照我的意愿去做。我正在使用现有数据和代码,所以我宁愿不更改数据库表定义或域对象。如果我们可以避免讨论领域模型设计那么好,那么还有比这个例子更多的内容。我有一个链接到这个项目的峰值here(假设数据库存在)

我目前的流利映射是:

public class ProductOverrides : IAutoMappingOverride<Product>
{
    public void Override(AutoMapping<Product> mapping)
    {
        mapping.Id(x => x.Id).Column("ProductId");            
        mapping.Table("Products");
    }
}

public class ConfigOverrides : IAutoMappingOverride<Config>
{
    public void Override(AutoMapping<Config> mapping)
    {
        mapping.Id(x => x.ConfigId);
    }
}

3 个答案:

答案 0 :(得分:4)

您正尝试将一对一关系映射为一对多关系,方法是将多方面两次映射。那不行。 NHibernate在一对一的定义上是严格的,并要求双方都有相同的主键,因此也不会有效。

butted heads with this before,我发现最好的解决方法是将其建模为标准的多对多,但只允许通过封装对它的访问来允许集合中的一个项目。在你的情况下,我猜测产品将是一方并且配置许多。

答案 1 :(得分:2)

我不确定Config是否在别处使用,但您可以忽略ConfigId作为其身份

public class Config
{
    public int Id { get; set; }
    public Product Product { get; set; }
    public string ConfigField1 { get; set; }
    public string ConfigField2 { get; set; }
}

public class ProductMap : ClassMap<Product>
{
    public class ProductMap()
    {
        HasOne(p => p.Config);
    }
}

public class ConfigMap : ClassMap<Config>
{
    public class ConfigMap()
    {
        Id(c => c.Id, "ProductId").GeneratedBy.Foreign("Product");

        References(c => c.Product, "ProductId");
        Map(c => ...);
    }
}

答案 2 :(得分:1)

另一个想法是加入并映射为Component

public class ProductMap : ClassMap<Product>
{
    public class ProductMap()
    {
        Join("Config", join => 
        {
            join.KeyColumn("ProductId");
            join.Component(p => p.Config, c =>
            {
                c.Map(...);
            });
        }
    }
}

缺点是您无法直接查询Config,您必须通过Product

进行查询