如何在 N-Tier 应用程序中使用 Fluent NHibernate?

Posted

技术标签:

【中文标题】如何在 N-Tier 应用程序中使用 Fluent NHibernate?【英文标题】:How to use Fluent NHibernate in N-Tier application? 【发布时间】:2010-07-16 06:35:43 【问题描述】:

我正在尝试在我的项目中采用 Fluent NHibernate,目前我可以从数据库中获取数据,当我在应用程序服务器时,数据包括它的 PK 但是当我将此数据(作为列表)返回给客户端时它的PK很松。

我该如何解决这个问题?

更新

我的 POCO 课程如下:PK 是 CountryCd 和 CityCd

public class coCity

    public virtual string CountryCd  get; private set; 
    public virtual string CityCd  get; private set; 
    public virtual string CityNameTH  get; set; 
    public virtual string CityNameEN  get; set; 
    public virtual int DeliveryLeadTime  get; set; 
    public virtual string CreateBy  get; set; 
    public virtual DateTime CreateDate  get; set; 
    public virtual string UpdateBy  get; set; 
    public virtual DateTime UpdateDate  get; set; 

    public override bool Equals(object obj)
    
        return this.GetHashCode().Equals(obj.GetHashCode());
    

    public override int GetHashCode()
    
        return (this.CountryCd + this.CityCd).GetHashCode();
    

映射类:

public class coCityMap : ClassMap<coCity>

    public coCityMap()
    
        Table("coCity"); // this is optional

        CompositeId()
            .KeyProperty(x => x.CountryCd)
            .KeyProperty(x => x.CityCd);
        Map(x => x.CityNameTH);
        Map(x => x.CityNameEN);
        Map(x => x.DeliveryLeadTime);
        Map(x => x.CreateBy);
        Map(x => x.CreateDate);
        Map(x => x.UpdateBy);
        Map(x => x.UpdateDate);
    

在应用服务器获取数据的源代码

public List<coCity> GetTest()

    List<coCity> result = new List<coCity>();

    var sessionFactory = CreateSessionFactory();

    using (var session = sessionFactory.OpenSession())
    
        result = (List<coCity>)session.CreateCriteria(typeof(coCity)).List<coCity>();
    

    return result;

当它仍然在应用服务器数据被正确检索时,如下图所示 alt text http://img138.imageshack.us/img138/1071/serverside.png

但是,当此数据传输回客户端时,其所有 PK 都松散,如下所示。 alt text http://img203.imageshack.us/img203/1664/clientside.png

【问题讨论】:

如果您展示您的一些代码(特别是您的 nHib 绑定​​)并澄清您所说的“它的所有 PK 都是松散的(原文如此)”的意思,那会容易得多。主键值是否真的消失了,就像重置为默认值一样,还是只是没有以明显的方式显示它们是主键? 而且在客户端和服务器之间序列化时不会丢失? @Stefan,如果我将 Serializable 添加到实体类,那么它的数据不会丢失,但我不知道这样做是否正确?无论如何,即使它的 PK 也没有松动,但是当我将此实体发送回服务器时,它总是尝试插入而不是更新。 【参考方案1】:

首先,这不是 Fluent NHibernate 的问题,所以:

    序列化 POCO 时,必须在 POCO 上使用 Serializable。 (来自您的评论)NHibernate 将从数据库中检索到的对象的引用保存到缓存(一级缓存)。当您序列化这个“托管”对象时,序列化的输出是一个非托管对象。 Nhibernate 不会仅仅因为您在新构造的对象中设置了值而检测到数据库中存在对象。您必须从数据库中获取对象并更新其属性并调用 Update() 或使用纯 sql 处理从客户端返回的对象(哎呀!)。

请注意,这与这个问题无关:您的 Equals() 实现非常糟糕,因为它没有考虑类型并且仅取决于 GetHashCode 值。如果你所有的类都有这个实现,你可能会遇到麻烦。

【讨论】:

【参考方案2】:

我认为问题在于 PK 属性上的私有设置器。尝试将其更改为公开。

不管怎样,用Serializable标记你的实体

几个cmets:

一般建议在使用 nhibernate 时避免使用复合 ID。在您的模型上创建一个作为标识列的代理 ID,并在其他地方强制执行 CityCd 和 CountryCd 的唯一性 在客户端/服务器层传递数据时,请考虑使用DTOs 以避免一些常见的 LazyInitializationExceptions 问题。

【讨论】:

以上是关于如何在 N-Tier 应用程序中使用 Fluent NHibernate?的主要内容,如果未能解决你的问题,请参考以下文章

什么是 N 层架构?

如何使用 Fluent 设置 NHibernate.Burrow?

[UWP]如何使用Fluent Design System (上)

如何使用 eloquent/fluent 从单个查询中更新多行?

如何使用Fluent API在具有ASC / DESC排序的多个列上添加索引?

如何使用 Fluent API 通过 ASC/DESC 排序在多列上添加索引?