1

您好,nhibernate 的一些专业人士可以给我每个对话或 unhaddins 实现的 Nhibernate 会话的示例实现吗?或解释如何做到这一点。最好的问候恩迪斯

4

1 回答 1

3

我使用 NHibernate 工作了 4 年。以前我使用“open-session-per-operation”反模式。对象总是分离的。因此,要坚持下去,我必须重新附加它们或将它们的值复制到附加对象。这会导致许多代码行和许多“延迟初始化异常”。

最近,我研究了“对话模式” ,并在“Spring.Net ”基础设施上做了一个实现。该实现已在Issue SPRNET-1431 (Workaround for 'conversation scope' and "session-per-conversation")提交给“jira.springsource”

我没有制作“示例应用程序”,但如果您有兴趣,我可以这样做。

海尔顿

补充答案:

我准备了示例应用程序并在SPRNET-1431 Workaround 中发布了“对话范围”和“会话每对话” 作为文件“Spring.Conversation.example.7z”。

下面,我写了解释来澄清(或不)我做了什么。

此“示例应用程序”是“Spring.NET”版本“1.3.0”中包含的“Spring.Data.NHibernate.Northwind”的修改,以使用 Conversation。目前,“Spring.Net”没有“会话范围”,也没有实现“Extended Persistence Context”(“会话每会话策略”)的概念。

在此示例应用程序中,目标是演示:

  1. 如何将对象的实例保持在“对话范围”的模仿中。显示在expression="@(convCustomer)['CustomerEditController']".
  2. 如何享受“扩展持久性上下文”。“延迟加载错误”不再发生,ISession.Get对“同一记录”的重复调用不会导致对数据库的多次访问,更有效地使用 NHibernate 缓存。对“CustomerList.aspx”的修改证明了这一点。要验证对话的有效性,请在“App_Code\ConversationPage.cs”行中添加注释,this.Conversation.StartResumeConversation();然后单击“CustomerList.aspx”上的“+”按钮会出现错误“无法延迟初始化角色集合” .

重要提示:切勿对整个应用程序使用单个会话(“HTTP 会话”的持续时间相同)。请记住,NHibernate 保留所有加载对象的缓存,如果会话保持很长时间,此缓存往往会无限增长(限制是数据库记录的数量)。也就是说,每个对话都应该限制在应用程序页面的一个子集内,并且必须在与该子集的交互结束时被丢弃(IConversationState.EndConversation())。建议:保留<property name="EndPaused" value="true"/>在“Spring.Conversation.Imple.WebConversationManager”中,以便在开始对话时丢弃其他对话。

附加信息:单元测试(“Spring.Northwind.IntegrationTests.2008”)不起作用。但是没有问题,因为它与为支持对话所做的更改无关,实际上它们甚至在此之前就已经导致错误。

“Spring.Data.NHibernate.Northwind”的变化列表:

  • Spring.Northwind.Web.References.2008
    • 添加到方案的链接以启用自动完成。
  • 网络配置

    • 模块,添加:

      <add 
        name="ConversationModule" 
        type="Spring.Conversation.HttpModule.ConversationModule, Spring.Conversation"/>  
      <add 
        name="ConversationModule" 
        type="Spring.Conversation.HttpModule.ConversationModule, Spring.Conversation"/>
      
    • 模块,已删除:

      <add 
        name="OpenSessionInView" 
        type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate21"/>
      
  • web.xml

    • 模块配置

      <!--Configuration for Spring HttpModule interceptor's-->
      <object 
         name="HttpApplicationConfigurer" 
         type="Spring.Context.Support.HttpApplicationConfigurer, Spring.Web">
        <property name="ModuleTemplates">
          <dictionary>
            <entry key="ConversationModule">
              <!-- this name must match the module name -->
              <object>
                <!-- 
                select "view source" in your browser on any page to 
                see the appended html comment
                -->
                <property name="ConversationManagerNameList">
                  <list element-type="string">
                    <value>conversationManager</value>
                  </list>
                </property>
              </object>
            </entry>
          </dictionary>
        </property>
      </object>
      
    • 对话管理器

      <!--Conversation Manager-->
      <object 
          name="conversationManager" 
          type="Spring.Conversation.Imple.WebConversationManager, Spring.Conversation" 
          scope="session">
        <property name="SessionFactory" ref="NHibernateSessionFactory"/>
        <property name="EndPaused" value="true"/>
      </object>
      
    • 客户对话

      <!--
       Conversation for 'CustomerEditor.aspx', 'CustomerList.aspx', 
       'CustomerOrders.aspx', 'CustomerView.aspx',  and 'FulfillmentResult.aspx'
      -->
      <!--
       Important: If the application had other parties
       ("management employees" for example), they should use another 
       conversation.
      -->
      <object 
          name="convCustomer" 
          type="Spring.Conversation.Imple.WebConversationSpringState, Spring.Conversation" 
          scope="session">
        <property name="Id" value="convCustomer"></property>
        <property name="TimeOut" value="0"></property>
        <property name="ConversationManager" ref="conversationManager"></property>
        <property name="SessionFactory" ref="NHibernateSessionFactory"/>
        <property name="DbProvider" ref="DbProvider"/>
        <!--
          Using workaround for 'conversation scope' to reference for 
          'CustomerEditController'. It is not as volatile as "request scope" 
          not as durable as the "session scope"
        -->
        <property name="['CustomerEditController']" ref="CustomerEditController"></property>
      </object>
      
    • 更改“CustomerEditController”范围,删除 [scope="session"] 并放入 [singleton="false"]:

      <object 
          name="CustomerEditController" 
          type="NHibernateCustomerEditController" 
          singleton="false">
        <constructor-arg name="sessionFactory" ref="NHibernateSessionFactory"/>
      </object>
      ...
      
    • 更改"CustomerEditController"、删除ref="CustomerEditController"和放置的参考expression="@(convCustomer)['CustomerEditController']"(模拟“对话范围”):

      <!--
        Using workaround for 'conversation scope' to reference for 
        'CustomerEditController'. It is not as volatile as "request scope" 
        not as durable as the "session scope"
      -->
      <object name="CustomerEditPage" abstract="true">
        <property 
          name="CustomerEditController" 
          expression="@(convCustomer)['CustomerEditController']"/>
        <property name="Conversation" ref="convCustomer"/>
      </object>
      
        <!--
          Using workaround for 'conversation scope' to reference for 
          'CustomerEditController'. It is not as volatile as "request scope" 
          not as durable as the "session scope"
        -->
        <object type="CustomerView.aspx">
          <property name="CustomerDao" ref="CustomerDao" />
          <property 
            name="CustomerEditController" 
            expression="@(convCustomer)['CustomerEditController']" />
          <property name="Conversation" ref="convCustomer"/>
          <property name="Results">
            <dictionary>
              <entry key="EditCustomer" value="redirect:CustomerEditor.aspx" />
              <entry key="CustomerList" value="redirect:CustomerList.aspx" />
            </dictionary>
          </property>
        </object>
        <!--
          Using workaround for 'conversation scope' to reference for 
          'CustomerEditController'. It is not as volatile as "request scope" 
          not as durable as the "session scope"
        -->
        <object type="FulfillmentResult.aspx">
          <property name="FulfillmentService" ref="FulfillmentService" />
          <property 
            name="CustomerEditController" 
            expression="@(convCustomer)['CustomerEditController']" />
          <property name="Conversation" ref="convCustomer"/>
          <property name="Results">
            <dictionary>
              <entry key="Back" value="redirect:CustomerOrders.aspx" />
            </dictionary>
          </property>
        </object>
        <object type="Default.aspx">
          <property name="Conversation" ref="convDefault"/>
          <property name="Results">
            <dictionary>
              <entry key="CustomerList" value="redirect:CustomerList.aspx" />
            </dictionary>
          </property>
        </object>
        <!--Conversation for 'Default.aspx'-->
        <!--
          "convDefault" will have only one functionality: trigger the release
          of other conversations when started (StartResumeConversation())
        -->
        <object
            name="convDefault" 
            type="Spring.Conversation.Imple.WebConversationSpringState, Spring.Conversation"
            scope="session">
          <property name="Id" value="convDefault"></property>
          <property name="TimeOut" value="0"></property>
          <property name="ConversationManager" ref="conversationManager"></property>
          <property name="SessionFactory" ref="NHibernateSessionFactory"/>
          <property name="DbProvider" ref="DbProvider"/>
        </object>
  • 添加了“ConversationPage.cs”。支持对话的基本页面。
  • 客户列表.aspx
    • 允许在同一页面上列出“订单”,而不会出现“延迟初始化错误”。所有对象都保持连接到 ISession (NHibernate)。
  • 客户列表.aspx.cs:
    • 添加属性IList<Customer> CustomersLoadedOncePerConvList。列表仅加载一次,每次对话仅搜索一次数据库。
    • 改变Page_InitializeControls考虑CustomersLoadedOncePerConvList
    • 该方法BtnShowOrders_Click隐含地在Customer.Orders.
  • 改为??? : Spring.Web.UI.Page开启??? : Spring.Web.UI.Page
    • CustomerEditor.aspx.cs
    • 客户列表.aspx.cs
    • CustomerOrders.aspx.cs
    • CustomerView.aspx.cs
    • FullfillmentResult.aspx.cs
    • 默认.aspx.cs
  • 道.xml

    • 添加<entry key="connection.release_mode" value="on_close"/>以避免在每个 IDbCommand 执行之前和之后断开和重新连接。这很重要,因为可能会在事务边界之外发生大量延迟加载。
    • 添加:

      ...
      <entry key="show_sql" value="true"/>
      <entry key="format_sql" value="true"/>
      ...
      
  • 从“Default.aspx.cs”中删除(它们从未使用过):

    • customerDao;
    • fulfillmentService;
    • CustomerDao;
    • Button1_Click(object sender, EventArgs e);
    • ProcessCustomer();
  • 配置\Log4Net.xml。

    ...
    <!--detail's about SQL's. To view sql commands on Logs\log.txt-->
    <logger name="NHibernate.SQL">
      <level value="DEBUG" />
    </logger>
    ...
    <!--detail's about Conversation-->
    <logger name="Spring.Conversation">
      <level value="DEBUG" />
    </logger>
    
于 2012-04-23T01:55:14.703 回答