【问题标题】:Save data through a web service using NHibernate?使用 NHibernate 通过 Web 服务保存数据?
【发布时间】:2010-12-10 06:59:07
【问题描述】:

我们目前有一个应用程序,它通过 Web 服务从服务器检索数据并填充 DataSet。然后 API 的用户通过对象来操作它,这些对象反过来又改变了数据集。然后将更改序列化、压缩并发送回服务器以进行更新。

然而,我已经开始在项目中使用 NHibernate,我真的很喜欢 POCO 对象的不连贯性。我们现在遇到的问题是,我们的对象与内部 DataSet 绑定在一起,以至于它们无法在许多情况下使用,最终导致重复的 POCO 对象来回传递。

Batch.GetBatch() -> calls to web server and populates an internal dataset
Batch.SaveBatch() -> send changes to web server from dataset 

有没有办法实现我们正在使用的类似模型,所有数据库访问都通过 Web 服务进行,但使用 NHibernate?

编辑 1

我有一个部分解决方案可以通过 Web 服务运行并持续存在,但它有两个问题。

  1. 我必须序列化并发送我的整个收藏,而不仅仅是更改的项目
  2. 如果我在返回对象时尝试重新填充集合,那么我拥有的所有引用都会丢失。

这是我的示例解决方案。

客户端

public IList<Job> GetAll()
{
    return coreWebService
      .GetJobs()
      .BinaryDeserialize<IList<Job>>();
}

public IList<Job> Save(IList<Job> Jobs)
{
    return coreWebService
             .Save(Jobs.BinarySerialize())
             .BinaryDeserialize<IList<Job>>();
}

服务器端

[WebMethod]
public byte[] GetJobs()
{
    using (ISession session = NHibernateHelper.OpenSession())
    {
        return (from j in session.Linq<Job>()
                select j).ToList().BinarySerialize();
    }
}

[WebMethod]
public byte[] Save(byte[] JobBytes)
{
    var Jobs = JobBytes.BinaryDeserialize<IList<Job>>();

    using (ISession session = NHibernateHelper.OpenSession())
    using (ITransaction transaction = session.BeginTransaction())
    {
        foreach (var job in Jobs)
        {
            session.SaveOrUpdate(job);
        }
        transaction.Commit();
    }

    return Jobs.BinarySerialize();
}

如您所见,我每次都将整个集合发送到服务器,然后返回整个集合。但我得到的是一个替换的集合,而不是一个合并/更新的集合。更不用说在只能更改部分数据的情况下来回发送所有数据似乎效率非常低。

编辑 2

我在网上看到了几篇关于几乎透明的持久性机制的参考资料。我不确定这些是否会起作用,而且它们中的大多数看起来都是实验性的。

我很难找到我们今天使用的 DataSet 模型的替代品。我想摆脱该模型的原因是因为将每个类的每个属性与数据集的行/单元格联系起来需要做很多工作。然后它也将我所有的类紧密地耦合在一起。

【问题讨论】:

  • 您的客户端和服务器是什么版本的 .net?您是否需要与非 .net 客户端进行通信?(或者您想要多紧密的耦合?)
  • 版本 3.5,我们不需要与 .NET 以外的任何东西进行互操作。就我而言,它可以完全绑定到.NET。我们构建客户端和服务器。

标签: web-services nhibernate dataset asmx


【解决方案1】:

我认为你的问题围绕着这个问题:

http://thatextramile.be/blog/2010/05/why-you-shouldnt-expose-your-entities-through-your-services/

您是否打算通过网络发送 ORM 实体?

因为你有一个面向服务的架构。我(和作者一样)不推荐这种做法。

我使用 NHibernate。我称这些 ORM 实体。他们是 POCO 模型。但它们具有允许延迟加载的“虚拟”属性。

不过,我也有一些 DTO 对象。这些也是 POCO 的。这些没有延迟加载友好属性。

所以我做了很多“转换”。我水合 ORM-Entities(使用 NHibernate)......然后我最终将它们转换为 Domain-DTO-Objects。是的,一开始很臭。

服务器发出 Domain-DTO-Objects 的。没有延迟加载。我必须用“Goldie Locks”“恰到好处”的模型来填充它们。也就是,如果我需要父母有一个级别的孩子,我必须事先知道这一点,然后通过这种方式发送 Domain-DTO-Objects,只需要适量的水合作用。

当我发回 Domain-DTO-Objects(从客户端到服务器)时,我必须反转这个过程。我将 Domain-DTO-Objects 转换为 ORM-Entities。并允许 NHibernate 使用 ORM-Entities。

因为架构是“断开的”,所以我做了很多 (NHiberntae) ".Merge()" 调用。

        // ormItem is any NHibernate poco
        using (ISession session = ISessionCreator.OpenSession())
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.BeginTransaction();
                ParkingAreaNHEntity mergedItem = session.Merge(ormItem);
                transaction.Commit();
            }
        }

.Merge 是一件很棒的事情。实体框架没有它。嘘。

这是很多设置吗?是的。 我认为它是完美的吗?没有。

但是。因为我向 ORM 发送了非常基本的 DTO(Poco),这些 DTO 没有“调味”,所以我有能力切换 ORM 而不会杀死我的合同到外部世界。

我的数据层可以是 ADO.NET、EF、NHibernate 或任何东西。如果我切换,我必须编写“转换器”和 ORM 代码,但其他一切都是隔离的。

很多人跟我争论。他们说我做的太多了,ORM-Entities 很好。

再次,我喜欢“现在允许任何延迟加载”的外观。而且我更喜欢隔离我的数据层。我的客户不应该知道或关心我选择的数据层/orm。

EF 和 NHibernate 之间存在足够细微的差异(或一些不那么细微的差异),足以搞砸游戏计划。

我的 Domain-DTO-Objects 看起来 95% 像我的 ORM-Entities 吗?是的。但它的 5% 可以搞砸你。

从数据集迁移,特别是如果它们是从 TSQL 中具有大量商业逻辑的存储过程填充的,则并非易事。但是现在我做了对象模型,而且我从不编写不是简单 CRUD 函数的存储过程,我永远不会回去。

而且我讨厌在存储过程中使用 voodoo TSQL 的维护项目。现在已经不是 1999 年了。嗯,大多数地方。

祝你好运。

PS 如果没有 .Merge(在 EF 中),这是您在断开连接的世界中必须做的事情:(boo microsoft)

http://www.entityframeworktutorial.net/EntityFramework4.3/update-many-to-many-entity-using-dbcontext.aspx

【讨论】:

  • 所以我可以理解这里关于不通过我的服务公开实体的观点。然而,我试图实现的一个主要部分是只将一个差异发送回服务器,而不是整个对象。使用 DataSet 很简单(即使它是耦合的)。
【解决方案2】:

我只是粗略地看了你的问题,如果我的回答是短视的,请原谅我,但这里是:

我认为您无法从逻辑上摆脱从域对象到 DTO 的映射。

通过在网络上使用域对象,您将客户端和服务紧密耦合,首先拥有服务的部分原因是促进松散耦合。所以这是一个迫在眉睫的问题。

最重要的是,您最终会得到一个脆弱的域逻辑接口,您无法在不破坏客户端的情况下在服务端进行更改。

我怀疑您最好的选择是实现一个松散耦合的服务,该服务实现一个 REST / 或其他一些松散耦合的接口。您可以使用 automapper 之类的产品来简化转换,并在必要时展平数据结构。

在这一点上,我不知道有什么方法可以真正减少做接口层所涉及的冗长,但是我曾参与过没有付出努力的大型项目,我可以诚实地告诉你,节省的钱不值得它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多