Отображение отношений между родителями и детьми nhibernate «другим» способом - PullRequest
2 голосов
/ 02 февраля 2012

с использованием 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 (?,?);

Я не хочу, чтобы это делалось, скорее я надеялся, что отображение сначала вставит Продукты, а затем - конфигурацию, а ProductId будет вставлено в таблицу конфигурации.

Я выдернул свои волосы, пытаясь переопределить и читать ссылки, такие как this и this , но все еще не могу заставить его делать то, что я хочу. Я работаю с существующими данными и кодом , поэтому я бы не стал изменять определения таблиц базы данных или объект домена. Здесь происходит нечто большее, чем то, что рисует этот пример, поэтому, если бы мы могли избежать дискуссий о разработке модели предметной области, это было бы здорово. У меня есть ссылка на шип этого проекта здесь (предполагается, что база данных существует)

мои текущие текущие отображения:

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 ]

4 голосов
/ 02 февраля 2012

Вы пытаетесь отобразить отношения один-к-одному как один-ко-многим, дважды отобразив то, что будет стороной многих. Это не сработает. NHibernate строг в своем определении «один к одному» и требует, чтобы обе стороны имели один и тот же первичный ключ, чтобы он тоже не работал.

У меня встык с этим до , и лучший найденный мной обходной путь - смоделировать его как стандартное для многих, но разрешить только один элемент в коллекции путем инкапсуляции доступа к нему. В вашем случае я бы предположил, что Product будет с одной стороны, а Config с множеством.

2 голосов
/ 02 февраля 2012

Я не уверен, что 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 => ...);
    }
}
1 голос
/ 02 февраля 2012

Другая идея состоит в том, чтобы присоединиться и отобразить как Компонент

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

Недостатком является то, что вы не можете запросить Config напрямую, вам нужно запросить через продукт

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...