NHibernate 3.1 忽略计算列公式

发布于 2024-11-03 01:58:59 字数 2197 浏览 4 评论 0原文

我有一个包含两个计算列的类。这些公式是从其他表中获取计数的 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'select TOP (@p0)business0_.Id as Id0_,business0_.UserPassword as UserPass2_0_,business0_.HasTakenSurvey as HasTaken3_0_,business0_.Votes as Votes0_,business0_.Origin as Origin0_,business0_.SecurityToken as 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 为 UserPos 14_0_,业务0_。 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 作为 UserMob 22_0_,business0_.UserEmailAddress 为UserEma23_0_、business0_.UserIpAddress 为 UserIpA24_0_、business0_.OptInReminders 为 OptInRe25_0_、business0_.OptInOffers 为 OptInOf26_0_、business0_.OptInSms 为 OptInSms0_、business0_.Created 为 Created0_、business0_.Modified 为 Modified0_ 来自 dbo.Businessesbusiness0_ 订单按business0_.BusinessName asc', N'@p0 int',@p0=25

实现是否发生变化?我做错了什么?

I have a class with two computed columns. The formulas are select statements that grab counts from other tables, like so:

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();
});

This was all working fine with Fluent NHibernate 1.1 (using NHibernate 2.1), but I just upgraded to 1.2 (using NH 3.1) and it appears that Fluent NHibernate is ignoring the formulas. I'm getting an "invalid column name" exception for the two fields HasTakenSurvey and Votes because its' trying to query the columns directly rather than executing the formulas as directed. An example query:

exec sp_executesql N'select TOP (@p0) business0_.Id as Id0_, business0_.UserPassword as UserPass2_0_, business0_.HasTakenSurvey as HasTaken3_0_, business0_.Votes as Votes0_, business0_.Origin as Origin0_, business0_.SecurityToken as Security6_0_, business0_.BusinessName as Business7_0_, business0_.BusinessType as Business8_0_, business0_.BusinessImageUrl as Business9_0_, business0_.BusinessDescription as Busines10_0_, business0_.EmployeeCount as Employe11_0_, business0_.OwnerFirstName as OwnerFi12_0_, business0_.OwnerLastName as OwnerLa13_0_, business0_.UserPosition as UserPos14_0_, business0_.BusinessAddress1 as Busines15_0_, business0_.BusinessAddress2 as Busines16_0_, business0_.BusinessCity as Busines17_0_, business0_.BusinessState as Busines18_0_, business0_.BusinessPostal as Busines19_0_, business0_.BusinessCountry as Busines20_0_, business0_.UserBusinessPhone as UserBus21_0_, business0_.UserMobilePhone as UserMob22_0_, business0_.UserEmailAddress as UserEma23_0_, business0_.UserIpAddress as UserIpA24_0_, business0_.OptInReminders as OptInRe25_0_, business0_.OptInOffers as OptInOf26_0_, business0_.OptInSms as OptInSms0_, business0_.Created as Created0_, business0_.Modified as Modified0_ from dbo.Businesses business0_ order by business0_.BusinessName asc',N'@p0 int',@p0=25

Did the implementation change? What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

栀子花开つ 2024-11-10 01:58:59

正如评论中所指出的 ConventionBuilder.Property.Always(x => 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();
});

As noted in the comments ConventionBuilder.Property.Always(x => x.Column(x.Property.Name)) was adding the column to all properties (and overriding the formula).

Adding .Columns.Clear() to the mapping should remove the column, so:

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();
});
情何以堪。 2024-11-10 01:58:59

@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));
        }
    }

Columns.Clear() solution provided by @david duffet also didn't work for me. The getter of Formula is private and so you can't filter on the Formula property (you get method-group cannot be converted to value or something like that). NH3.3, FNH 1.3.

My solution - create a custom Attribute in my Model project - IsNHibernateFormulaPropertyAttribute, apply it to my formula properties, and then check for that attribute in my naming convention logic using reflection:

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));
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文