对于多表实体,仅保存一个表

时间:2010-11-29 20:02:36

标签: c# nhibernate fluent-nhibernate nhibernate-mapping

我有一个实体,由我描述here的两个不同的表中的属性组成,当我尝试插入一个新项时,我遇到了问题。插入时我只需要更新两个表中的一个表中的字段。使用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 :(得分:0)

好的,在考虑了迭戈的评论并获得良好的睡眠后,我想出了实现这一点并获得我想要的结果的正确方法。迭戈是对的,我应该使用Reference而不是Join。我想要将其作为连接实现的原始推理是希望避免在我的对象图中添加另一个级别。 AccountRegistrationField已经是Account对象上的属性,我不想像Account.AccountRegistrationField.RegistrationField.FieldType那样拨打电话。我反而希望调用是Account.AccountRegistrationField.FieldType,因为我真正操作的对象是AccountRegistrationField对象。

通过更好地设计我的AccountRegistrationField课程,我能够获得这种行为。我将RegistrationField属性设为私有,并在AccountRegistrationField类上添加了公共属性,以显示我需要的字段。然后使用Fluent NHibernate的Reveal类将私有属性公开给我的映射。

我的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");

    }
}