【问题标题】:Property Mapping based on dynamic criteria at runtime运行时基于动态标准的属性映射
【发布时间】:2011-01-21 04:06:06
【问题描述】:

我一直在谷歌上筛选页面寻找答案,但无济于事,但我认为我只是用错了措辞。

场景如下:我有一个用户可以投票赞成或反对的实体。为了争论,让我们称实体为企业。

我想在我的业务类上拥有一个属性,该属性指示当前登录的用户如何为该特定业务投票。即我想在用户支持的地方显示一个绿色的勾,在用户投票的地方显示一个红十字。

在 SQL 中这是直截了当的,我可以创建一个 SQL 函数,该函数根据参数“:userid”更具体地执行此解析,该参数可以传递到 proc 中。即

   SELECT
      BusinessId,
      CreatedOn,
      Username,
      [Content].ResolveBusinessVoteIndicator(:userid, P.BusinessId) AS VoteIndicator
   FROM 
      Content.Business P

这里的主要问题是我必须创建一个映射到存储过程结果的实体。这很糟糕,因为现在我不能使用 HQL 或 Criteria,这将是选择的方法。

另一种选择是进行查询,然后简单地遍历结果并设置该属性,如果您一次查看一个业务,这将起作用,但我需要一次显示大量业务.

所以我想问题是......有没有办法使用 HQL 或 Criteria 映射属性,其中该映射基于需要在运行时输入的公式?类似于将参数传递给存储过程并映射出结果。

【问题讨论】:

  • 我建议研究 NHibernate 公式和预测。

标签: c# nhibernate hql criteria


【解决方案1】:

在这种情况下,您实际上是在谈论 ViewModel。您不应该在业务实体上拥有该属性,而应该创建一个视图模型来表示具有您正在谈论的标志的业务实体。

如果你真的想用 NHibernate 做到这一点,在你的数据库中创建一个视图并将视图模型映射到视图。然后你可以像任何其他对象一样对它运行 HQL / Criteria。我已经做了很多,而且效果很好。

您还可以使用数据集从存储的过程中获取结果,并绑定到数据集。请记住,您的域模型(业务实体)与您的视图模型(business-with-vote 类)不同,可能不应该从相同的数据访问代码运行。

Greg Young 在他的博客上经常谈到这种方法。例如:http://codebetter.com/blogs/gregyoung/archive/2010/02/15/cqrs-is-more-work-because-of-the-read-model.aspx

【讨论】:

    【解决方案2】:

    如果您想为每个业务需求创建一个视图,Derick 的回答是一个合理的答案。

    您想要完成的任务可以通过IFilter 完成。 考虑 Business 类上的这个 hbm.xml 映射属性

    <property name="IsVoted" type="boolean" update="false" insert="false" formula="(SELECT [Content].ResolveBusinessVoteIndicator(:loggedOnUser.userId, BusinessId)"/>
    

    以及课程本身

     public bool IsVoted {get;set;}
    

    注意ResolveBusinessVoteIndicator 存储过程中的BusinessId 参数必须是Business 表的Id 列,NHibernate 将为它创建适当的别名。 现在,这取决于可以在单独的文件中定义的以下 xml 元素(比如说 filters.hbm.xml)

    <?xml version="1.0" encoding="utf-8"?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
        <filter-def name="loggedOnUser">
            <filter-param name="userId" type="Int32"/>
        </filter-def>
    </hibernate-mapping>
    

    在运行时,您可以像这样以编程方式启用过滤器

    nhSession.EnableFilter("loggedOnUser").SetParameter("userId", GetLoggedOnUserId());
    

    在运行查询之前。此外,您可以直接在 hql 中使用它(伪 hql:'from Business b where b.IsVoted = true' 以获取所有投票的企业)

    【讨论】:

    • 感谢 Jaguar,我花了一些时间实施您的建议,在 sql 方言等中注册用户定义的函数后,我收到以下错误:参数化查询 '(@p0 nvarchar(4),@p1 nvarchar(4),@p2 nvarchar(4000))select top 1' 需要未提供的参数“@p2”。我使用 SQL 查询分析器将查询跟踪到 SQL,并且 userId 字段没有被替换属性,而是以@p2 的身份访问 sql,而不是在 EnableFilter 步骤中设置的用户名。有什么想法吗?
    • PS - 实际查询如下 var query = NSessionManager.Current.Session.CreateQuery(@" from BusinessEntry where TopExperience.CreatedBy.Username = :username order by Votes desc ") .SetString("用户名", 用户名) .SetFirstResult(skip) .SetMaxResults(take); return query.List().ToList();
    • 出了点问题.... 通常,当过滤器无法传递参数时,查询中会留下字符串 ':loggedOnUser.userId'。除此之外,我在您的错误消息中看到 3 个参数(@p0、@p1、@p2),尽管您正在创建 2...一个来自过滤器,一个来自 HQL 查询本身。你能发布映射、类(至少是相关部分)和代码示例来进行获取吗?
    猜你喜欢
    • 2012-07-31
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    相关资源
    最近更新 更多