代码之家  ›  专栏  ›  技术社区  ›  Nathan Palmer

使用NHibernate通过web服务保存数据?

  •  3
  • Nathan Palmer  · 技术社区  · 15 年前

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

    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

    我很难找到一个替代我们今天使用的数据集模型。我想摆脱这个模型的原因是,将每个类的每个属性与数据集的行/单元格绑定起来需要大量的工作。然后它也把我所有的课程紧密地结合在一起。

    2 回复  |  直到 13 年前
        1
  •  0
  •   John Saunders    13 年前

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

    我不认为您可以从逻辑上摆脱从域对象到DTO的映射。

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

    除此之外,你将最终得到一个脆弱的域逻辑接口,在那里你不能在不破坏你的客户端的情况下对服务进行更改。

    我想最好的办法是实现一个松散耦合的服务,它实现一个REST/或其他一些松散耦合的接口。您可以使用automapper这样的产品来简化和简化转换,并在必要时展开数据结构。

    在这一点上,我不知道有什么方法可以真正减少在做接口层时的繁琐工作,但我曾在一些大型项目上工作,但这些工作没有做出努力,我可以诚实地告诉你,节省下来的钱不值得。

        2
  •  0
  •   granadaCoder    11 年前

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

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

    你是要还是不打算通过网络发送ORM实体?

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

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

    所以我做了很多“转换”。我水合ORM实体(用NHibernate)…然后我把它们转换成领域数据到对象。是的,一开始就很臭。

    服务器将域数据发送到对象的。不存在延迟加载。我得用“Goldie Locks”“just right”模型填充它们。也就是说,如果我需要有一个级别的子级的父级,我必须预先知道这一点,并通过这种方式将域DTO发送给对象,并且只需适当的水合量。

    当我把域数据发送回对象的(从客户机到服务器)时,我必须反转这个过程。我将域DTO对象转换为ORM实体。并允许NHibernate与ORM实体合作。

    因为架构是“断开连接”的,所以我做了很多(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();
                }
            }
    

    合并是件好事。实体框架没有它。喝倒采。

    这是一堆装置吗?对。 我觉得它完美吗?不。

    然而。因为我向ORM发送的是非常基本的DTO(Poco's),这些DTO不是“有味道的”,所以我有能力切换ORM而不会破坏我与外界的合同。

    很多人和我争论。他们说我做的太多了,ORM实体还不错。

    英孚和NHibernate之间有足够的细微差别(或一些不那么细微的差别)来破坏游戏计划。

    我的域DTO对象看起来95%像我的ORM实体吗?是的。但那5%会让你发疯。

    从数据集迁移,尤其是如果它们是从TSQL中有大量biz逻辑的存储过程填充的,这并不是一件小事。但是现在我做了对象模型,而且我从来没有写过一个不是简单的CRUD函数的存储过程,我再也不会回去了。

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

    祝你好运。

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