NHibernate 3.1忽略计算列公式

时间:2011-04-22 17:30:05

标签: nhibernate fluent-nhibernate

我有一个包含两个计算列的类。公式是从其他表中获取计数的select语句,如下所示:

private const string VOTES_FORMULA = "(select count(v.id) from Votes v where v.BusinessID = Id)";
private const string SURVEY_FORMULA = "(select cast((case when exists (select * from surveys s where s.businessid = Id) then 1 else 0 end) as bit))";

// in my bootstrap code...
mappings.Override<Business>(map =>
{
    map.IgnoreProperty(x => x.IsNewRecord);
    map.IgnoreProperty(x => x.IdString);
    map.Map(x => x.UserPassword).CustomType<EncryptedStringType>();
    map.Map(x => x.HasTakenSurvey).Formula(SURVEY_FORMULA).Not.Insert().Not.Update();
    map.Map(x => x.Votes).Formula(VOTES_FORMULA).Not.Insert().Not.Update();
});

这一切都与Fluent NHibernate 1.1(使用NHibernate 2.1)完美配合,但我刚升级到1.2(使用NH 3.1),看起来Fluent NHibernate忽略了公式。我得到两个字段HasTakenSurvey和Votes的“无效列名”例外,因为它'试图直接查询列而不是按照指示执行公式。一个示例查询:

exec sp_executesql N选择TOP(@ p0)business0_.Id为Id0_,business0_.UserPassword为UserPass2_0_,business0_.HasTakenSurvey为HasTaken3_0_,business0_。投票为Votes0_,business0_.Origin为Origin0_,business0_.SecurityToken为Security6_0_,business0_ .BusinessName为Business7_0_,business0_.BusinessType为Business8_0_,business0_.BusinessImageUrl为Business9_0_,business0_.BusinessDescription为Busines10_0_,business0_.EmployeeCount为Employe11_0_,business0_.OwnerFirstName为OwnerFi12_0_,business0_.OwnerLastName为OwnerLa13_0_,business0_.UserPosition为UserPos14_0_,business0_.BusinessAddress1如Busines15_0_,business0_.BusinessAddress2如Busines16_0_,business0_.BusinessCity如Busines17_0_,business0_.BusinessState如Busines18_0_,business0_.BusinessPostal如Busines19_0_,business0_.BusinessCountry如Busines20_0_,business0_.UserBusinessPhone如UserBus21_0_,business0_.UserMobilePhone如UserMob22_0_,business0_.UserEmailAddress如UserEma23_0_ ,business0_.U serIpAddress为UserIpA24_0_,business0_.OptInReminders为OptInRe25_0_,business0_.OptInOminders为OptInOf26_0_,business0_.OptInSms为OptInSms0_,business0_.Created为Created0_,business0_.Modified为Modified0_ from dbo.Businesses business0_ order by business0_.BusinessName asc',N'@ p0 INT”,@ P0 = 25

实施是否改变了?我做错了什么?

2 个答案:

答案 0 :(得分:2)

如注释中所述,ConventionBuilder.Property.Always(x =&gt; x.Column(x.Property.Name))将列添加到所有属性(并覆盖公式)。

在映射中添加.Columns.Clear()应该删除列,所以:

mappings.Override<Business>(map =>
{
    map.IgnoreProperty(x => x.IsNewRecord);
    map.IgnoreProperty(x => x.IdString);
    map.Map(x => x.UserPassword).CustomType<EncryptedStringType>();
    map.Map(x => x.HasTakenSurvey).Formula(SURVEY_FORMULA).Not.Insert().Not.Update().Columns.Clear();
    map.Map(x => x.Votes).Formula(VOTES_FORMULA).Not.Insert().Not.Update().Columns.Clear();
});

答案 1 :(得分:0)

@david duffet 提供的 Columns.Clear() 解决方案也不适用于我。 Formula 的 getter 是私有的,所以你不能过滤 Formula 属性(你得到的方法组不能转换为值或类似的东西)。 NH3.3,FNH 1.3。

我的解决方案 - 在我的模型项目中创建一个自定义属性 - IsNHibernateFormulaPropertyAttribute,将其应用于我的公式属性,然后使用反射在我的命名约定逻辑中检查该属性:

private bool IsFormula(IPropertyInstance instance)
{
    var propInfo = instance.Property.DeclaringType.GetProperty(instance.Property.Name);
    if (propInfo != null)
    {
        return Attribute.IsDefined(propInfo, typeof(IsNHibernateFormulaPropertyAttribute));
    }

    return false;
}
public void Apply(IPropertyInstance instance)
    {
        if (!IsFormula(instance))
        {
            instance.Column(Convert(instance.Property.Name));
        }
    }