Обновление только одной таблицы при сохранении для объекта с несколькими таблицами - PullRequest
0 голосов
/ 29 ноября 2010

У меня есть объект, который состоит из свойств из двух разных таблиц, как я описал здесь , и у меня возникают проблемы, когда я пытаюсь вставить новый элемент. При вставке мне нужно только обновить поля в одной из двух таблиц. Используя метод ReadOnly(), я смог заставить NHibernate игнорировать большинство полей из [RegistrationField] при сохранении. Однако я не могу заставить его не пытаться сохранить новую запись в [RegistrationField] для внешнего ключа, даже если запись для этого ключа уже существует.

Мое сопоставление для класса:

public class RegistrationFieldMap : ClassMap<RegistrationField>
{
    public RegistrationFieldMap()
    {
        Table("AccountRegistrationField");

        Id(r => r.ID).Column("RegistrationID");
        Map(r => r.AccountID);
        Map(r => r.DefaultValue);
        Map(r => r.FieldID);
        Map(r => r.IsRequired);
        Map(r => r.Label);
        Map(r => r.Priority);
        Join("RegistrationField", t =>
        {
            t.Map(r => r.FieldType).ReadOnly();
            t.Map(r => r.HtmlID).ReadOnly();
        });
    }
}

Когда я запускаю свой тест для проверки соответствия, NHibernate пытается выполнить следующие два оператора SQL:

INSERT INTO AccountRegistrationField (
    AccountID, 
    DefaultValue, 
    FieldID, 
    IsRequired, 
    Label, 
    Priority) 
VALUES (@p0, @p1, @p2, @p3, @p4, @p5); 
select SCOPE_IDENTITY();
@p0 = 1 [Type: Int32 (0)], 
@p1 = 'bar' [Type: String (4000)], 
@p2 = 1 [Type: Int32 (0)], 
@p3 = False [Type: Boolean (0)], 
@p4 = 'bar' [Type: String (4000)], 
@p5 = 1 [Type: Int32 (0)]

INSERT INTO RegistrationField (UserRegistrationField_id) VALUES (@p0);
@p0 = 12 [Type: Int32 (0)]

Мне нужно только запустить первый оператор, поскольку таблица [RegistrationField] содержит статический список значений, и новые элементы никогда не должны добавляться в него.

Любые предложения приветствуются.

1 Ответ

0 голосов
/ 30 ноября 2010

Хорошо, подумав над комментарием Диего и хорошо выспавшись, я придумал, как правильно реализовать это и получить желаемый результат. Диего прав, что я должен использовать Reference, а не Join. Моим первоначальным аргументом в пользу того, чтобы реализовать это как объединение, было желание избежать добавления другого уровня в мой граф объектов. AccountRegistrationField уже является свойством объекта Account, и я не хотел совершать вызов, подобный Account.AccountRegistrationField.RegistrationField.FieldType. Вместо этого я хотел, чтобы вызов был Account.AccountRegistrationField.FieldType, поскольку объект, над которым я действительно буду работать, - это AccountRegistrationField объект.

Я смог добиться такого поведения, немного улучшив свой класс AccountRegistrationField. Я сделал свойство RegistrationField закрытым и добавил открытые свойства в классе AccountRegistrationField, чтобы открыть нужные мне поля. А затем использовал класс Reveal для Fluent NHibernate, чтобы открыть частную собственность для моего отображения.

Мой AccountRegistrationField класс в итоге выглядел так:

public class AccountRegistrationField
{
    public virtual int ID { get; set; }
    public virtual int AccountID { get; set; }
    public virtual string DefaultValue { get; set; }
    public virtual int FieldID { get; set; }
    public virtual string HtmlID 
    { 
        get { return RegistrationField.HtmlID; } 
    }
    public virtual bool IsRequired { get; set; }
    public virtual string Label { get; set; }
    public virtual int Priority { get; set; }
    public virtual string FieldType 
    { 
        get { return RegistrationField.FieldType; } 
    }

    private RegistrationField RegistrationField { get; set; }
}

И мое отображение для AccountRegistrationField выглядит так:

public class AccountRegistrationFieldMap : ClassMap<AccountRegistrationField>
{
    public AccountRegistrationFieldMap()
    {
        Table("AccountRegistrationField");

        Id(r => r.ID).Column("RegistrationID");
        Map(r => r.AccountID);
        Map(r => r.DefaultValue);
        Map(r => r.IsRequired);
        Map(r => r.Label);
        Map(r => r.Priority);
        References<RegistrationField>(
                 Reveal.Member<AccountRegistrationField>("RegistrationField"))
            .Column("FieldID");

    }
}
...