Free Hit Counters
http://www.dellasdeals.com

海天小阁

一个生于70年代的IT人,高不成低不就,与君共勉

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  65 随笔 :: 0 文章 :: 793 评论 :: 18 引用

本文通过比较Hibernate3.0ADO.net 2.0对数据库存储过程的执行来比较两者的基本情况。

由于本人对Hibernate不熟悉,所有Hibernate代码均转载自http://java.e800.com.cn/articles/2007/515/1179165860296629767_1.html

如果有任何不恰当的地方请多多指教

本文的目的是

如果Nhibernate没有其它的过人之处,在.net环境下要他干嘛呢?

主要还是更针对在.net环境下的NHibernate

微软的ADO.net有着良好的结构。看见很多人在研究ORM。由于对具体的ORM产品没有过多了解,因此感觉这些产品存在的意义似乎不大?

下面表格的比较,试图说明,ADO本身也已经支持对象持久化。如果仅仅是单独一个对象对应一个表或者一行数据,似乎根本不需要使用任何的ORM产品

如果我的论断是对的,那么很多ORM可以洗洗睡了。园子里的某些“兴趣组”也可以关门了

-----------------------------------------------------------------
2007-09-14 14:06 henry
多体验一下NHibernate的对象化操作,而不是简单对象添加,删除和查询.
-----------------------------------------------------------------

我觉得在微软的Linq里面非常强大得可以对对象进行各种操作。自然,在没有Linq支持的地方可能NHibernate的作用能够体现出来一些。算是本贴的第一个成果。

那么,在完全支持Linq的地方NHibernate就没有用处了吧?


------------------------------------------------------------------
2007-09-14 17:11 henry

到底现在Linq是不是真的利害到可以扼杀一切还没有定断,我看来现版本的Linq在数据操远达到SQL优雅高效,唯的好处就是借助于编译器实现检测(不 过的确可以节省很大调试成本,但对于其编写简洁性有所保留),如果编译器直接直入SQL并根据查询返回动太对象类型那这个时候Linq就走一边去了.任何 事物都在发展的别看了一个东西有些甜头就把别东西看成一坨屎......
-------------------------------------------------------------------

恩,那么本主题的最后结论可能是这样的:
不考虑Linq、ADO3.0等未来的变化
目前ADO.net2.0完全可以胜任将数据表映射成对象的操作,以及提供对象间的关系操作
但是NHibernet扩展了强大的面向对象的数据操作性能,可以让程序员方便得以对象的方式进行很多操作,而不用去关心数据库访问的细节。这个是ADO.net不能做到的

因此如果有人不好好学习NHibernate
仅仅拿来做做增删改查
那么最好不要到处跟人家说,俺项目里用了NHibernate
因为丢人家NHibernate的脸


步骤

作用

Hibernate

ADO.net 2.0

数据源连接配置

设定连接到什么数据据库以及具体的连接参数

所在文件:hibernate的配置文件

<property name="connection.url">jdbc:mysql://localhost:3306/test</property>

   <property name="connection.username">root</property>

   <property name="connection.password">root</property>

   <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

   <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

所在文件:app.config

<configuration>

    <configSections>

    </configSections>

    <connectionStrings>

        <add name="WindowsApplication1.Properties.Settings.TestConnectionString"

            connectionString="Data Source=."SQLEXPRESS;AttachDbFilename=|DataDirectory|"Test.mdf;Integrated Security=True;User Instance=True"

            providerName="System.Data.SqlClient" />

    </connectionStrings>

</configuration>

实体类

所谓ORM里面程序中使用到的业务对象类

所在文件:User.java

public class User implements java.io.Serializable {

private static final long serialVersionUID = 1L;

/** 用户id*/

private String userid;

/** 用户姓名*/

private String name;

/** 用户blog*/

private String blog;

//省略get/set方法

}

所在文件:TestDataSet.Designer.cs

        /// <summary>

        ///Represents strongly named DataRow class.

        ///</summary>

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")]

        public partial class tbl_userRow : global::System.Data.DataRow {

            private tbl_userDataTable tabletbl_user;

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            internal tbl_userRow(global::System.Data.DataRowBuilder rb) :

                    base(rb) {

                this.tabletbl_user = ((tbl_userDataTable)(this.Table));

            }

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            public string userid {

                get {

                    return ((string)(this[this.tabletbl_user.useridColumn]));

                }

                set {

                    this[this.tabletbl_user.useridColumn] = value;

                }

            }

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            public string name {

                get {

                    try {

                        return ((string)(this[this.tabletbl_user.nameColumn]));

                    }

                    catch (global::System.InvalidCastException e) {

                        throw new global::System.Data.StrongTypingException("表“tbl_user”中列“name”的值为 DBNull", e);

                    }

                }

                set {

                    this[this.tabletbl_user.nameColumn] = value;

                }

            }

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            public string blog {

                get {

                    try {

                        return ((string)(this[this.tabletbl_user.blogColumn]));

                    }

                    catch (global::System.InvalidCastException e) {

                        throw new global::System.Data.StrongTypingException("表“tbl_user”中列“blog”的值为 DBNull", e);

                    }

                }

                set {

                    this[this.tabletbl_user.blogColumn] = value;

                }

            }

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            public bool IsnameNull() {

                return this.IsNull(this.tabletbl_user.nameColumn);

            }

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            public void SetnameNull() {

                this[this.tabletbl_user.nameColumn] = global::System.Convert.DBNull;

            }

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            public bool IsblogNull() {

                return this.IsNull(this.tabletbl_user.blogColumn);

            }

            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

            public void SetblogNull() {

                this[this.tabletbl_user.blogColumn] = global::System.Convert.DBNull;

            }

        }

映射关系

指定在程序中使用的实体类与数据库中实际表以及列之间的关联关系

所在文件:User.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.amigo.proc.model">

    <class name="User" table="tbl_user">

        <id name="userid" column="userid">

            <generator class="assigned"/>

        </id>

        <property name="name" column="name" type="string" />

        <property name="blog" column="blog" type="string" />

    </class>

    <sql-query name="getUserList" callable="true">

 <return alias="user" class="User">

   <return-property name="userid" column="userid"/>

   <return-property name="name" column="name"/>

   <return-property name="blog" column="blog" />

 </return>

 {call getUserList()}

 </sql-query>

</hibernate-mapping>

所在文件:TestDataSet.Designer.cs

global::System.Data.Common.DataTableMapping tableMapping = new global::System.Data.Common.DataTableMapping();

            tableMapping.SourceTable = "Table";

            tableMapping.DataSetTable = "tbl_user";

            tableMapping.ColumnMappings.Add("userid", "userid");

            tableMapping.ColumnMappings.Add("name", "name");

            tableMapping.ColumnMappings.Add("blog", "blog");

…………

private void InitCommandCollection() {

            this._commandCollection = new global::System.Data.SqlClient.SqlCommand[1];

            this._commandCollection[0] = new global::System.Data.SqlClient.SqlCommand();

            this._commandCollection[0].Connection = this.Connection;

            this._commandCollection[0].CommandText = "dbo.getUserList";

            this._commandCollection[0].CommandType = global::System.Data.CommandType.StoredProcedure;

            this._commandCollection[0].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@RETURN_VALUE", global::System.Data.SqlDbType.Variant, 0, global::System.Data.ParameterDirection.ReturnValue, 0, 0, null, global::System.Data.DataRowVersion.Current, false, null, "", "", ""));

        }

其它存储过程省略……

查询


// 测试实现查询的存储过程

 private void testProcQuery(Session session) throws Exception ...{

 //查询用户列表

        List list = session.getNamedQuery("getUserList").list();

        for (int i = 0; i < list.size(); i++) ...{

            User user = (User) list.get(i);

            System.out.print("序号: " + (i+1));

            System.out.print(", userid: " + user.getUserid());

            System.out.print(", name: " + user.getName());

            System.out.println(", blog: " + user.getBlog());

        }

 }

private void testProcQuery()
        {
            //定义用户类集合
            TestDataSet.tbl_userDataTable Users = new TestDataSet.tbl_userDataTable();
            //获得数据
            this.tbl_userTableAdapter1.Fill(Users);
            int i = 0;
            //显示内容
            foreach(TestDataSet.tbl_userRow User in Users)
            {
                System.Console.WriteLine(string.Concat("序号:", i++, ",用户ID:", User.userid, ",用户姓名:", User.name, ",Blog:", User.blog));
            }
        }

更新


/**//**

 * 测试实现更新的存储过程

 * @throws Exception

 */

 private void testProcUpdate(Session session) throws Exception ...{

 //更新用户信息

 Transaction tx = session.beginTransaction();

        Connection con = session.connection();

        String procedure = "{call updateUser(?, ?, ?)}";

        CallableStatement cstmt = con.prepareCall(procedure);

        cstmt.setString(1, "xx");

        cstmt.setString(2, "http://www.blogjava.net/sterningChen");

        cstmt.setString(3, "sterning");

        cstmt.executeUpdate();

        tx.commit();

 }

private void testProcUpdate()
        {
            //类似Java的写法
            this.tbl_userTableAdapter1.Update("newID", "陈xx", "http://www.blogjava.net/sterningChen");

            //使用业务对象的写法
            //GetUsserByUserID是另一个因存储过程而产生的方法,自动生成的,以下同
            TestDataSet.tbl_userRow user = this.tbl_userTableAdapter1.GetUserByUserID("NewUserID")[0];
            user.name = "newName";
            user.blog = "newBlog";
            this.tbl_userTableAdapter1.Update(user);
        }

插入


// 测试实现插入的存储过程

 private void testProcInsert(Session session) throws Exception ...{

 //创建用户信息

 session.beginTransaction();

        PreparedStatement st = session.connection().prepareStatement("{call

createUser(?, ?, ?)}");

        st.setString(1, "amigo");

        st.setString(2, "阿蜜果");

        st.setString(3, "http://www.wblogjava.net/amigoxie");

        st.execute();

        session.getTransaction().commit();

 }

private void testProcInsert()
        {
            //直接使用数据
            this.tbl_userTableAdapter1.Insert("newID", "newName", "newBlog");  
            //使用面向对象
            TestDataSet.tbl_userDataTable tb = new TestDataSet.tbl_userDataTable();
            TestDataSet.tbl_userRow user = tb.Newtbl_userRow();
            user.userid = "NewUserID";
            user.name = "NewUser";
            user.blog = "testBlog";
            tb.Addtbl_userRow(user) ;
            this.tbl_userTableAdapter1.Update(user);  
        }


// 测试实现删除的存储过程

 private void testProcDelete(Session session) throws Exception ...{

 //删除用户信息

 session.beginTransaction();

 PreparedStatement st = session.connection().prepareStatement("{call deleteUser

(?)}");

        st.setString(1, "amigo");

        st.execute();

        session.getTransaction().commit();

 }

 private void testProcDelete()
        {
            //直接使用UserID删除
            this.tbl_userTableAdapter1.Delete("newID");

            //面向对象的方法
            TestDataSet.tbl_userRow user = this.tbl_userTableAdapter1.GetUserByUserID("NewUserID")[0];
            user.Delete();
            this.tbl_userTableAdapter1.Update(user);  
        }





posted on 2007-09-14 12:33 徐少侠 阅读(4679) 评论(70) 编辑 收藏

评论

#1楼[楼主] 2007-09-14 13:03 徐少侠      
本文的.net代码仅为和Java比较,并不是实际的良好.net代码

因为,当使用了数据链路(DataBinding 既数据绑定)后,从界面到数据库的数据传递将大部分由自动化的代码完成。
 回复 引用 查看   

#2楼 2007-09-14 13:14 94[未注册用户]
是我理解有问题还是怎么了,压根就没搞懂楼主想说什么
 回复 引用   

#3楼 2007-09-14 13:20 暗香浮动      
只有数据没有结论。
 回复 引用 查看   

#4楼[楼主] 2007-09-14 13:22 徐少侠      
由于上网不方便,因此各位弟兄的高见可能要到周1才能拜读,见谅。
 回复 引用 查看   

#5楼[楼主] 2007-09-14 13:25 徐少侠      
我的意思是,根本没有必要使用多余的ORM产品

微软自身的东西已经足够使用了

自然,还没有测试性能的问题
 回复 引用 查看   

#6楼 2007-09-14 13:26 Spring.Cheung      
我也没搞懂。丷
 回复 引用 查看   

#7楼 2007-09-14 13:30 kiler      
@徐少侠

那你还用.net framework干什么,用汇编算了,性能足够好。

比较性能有意义吗,Nhibernate就是基于ado.net的封装。

Nhibernate最大优势是在于对于使用者来说尽可能的减少了sql语句的使用,无需使用sql就可以完成很多常用的数据操作,你在开发的时候再也不用绞尽脑汁的考虑sql的编写优化这些问题。
 回复 引用 查看   

#8楼[楼主] 2007-09-14 13:37 徐少侠      
--引用--------------------------------------------------
kiler: @徐少侠

那你还用.net framework干什么,用汇编算了,性能足够好。
--------------------------------------------------------
我正在用framework在说问题

如果在framework内部已经有了一个足够好的解决方案,那为什么还需要一个看不出什么特色的方案呢?

我的发文目的,是和那些认为NHibernate有存在意义的人讨论。NHibernate存在的意义究竟是什么?

因为我没有看出来,因为我不狠懂NHibernate,希望这里了解这一产品的人对我进行教育

其实我们做软件的都有一个习惯。

要我使用一个新东西,必须要有理由的。

用NHibernate需要学习新的东西,那么必须要有一些理由让我们去值得学习
 回复 引用 查看   

#9楼[楼主] 2007-09-14 13:40 徐少侠      
--引用--------------------------------------------------
kiler: @徐少侠

那你还用.net framework干什么,用汇编算了,性能足够好。

比较性能有意义吗,Nhibernate就是基于ado.net的封装。

Nhibernate最大优势是在于对于使用者来说尽可能的减少了sql语句的使用,无需使用sql就可以完成很常用的数据操作,你在开发的时候再也不用绞尽脑汁的考虑sql的编写优化这些问题。

--------------------------------------------------------
无需使用SQL
那么NHibernate使用什么和数据库交互?
仅仅是封装起来没有让用户直接编写罢了

那么请看看我上面的例子,我在进行数据库操作时候也没有写任何一SQL语句阿
这些方法都是framework根据存储过程自动生成的

 回复 引用 查看   

#10楼[楼主] 2007-09-14 13:41 徐少侠      
因此 ,说NHibernate相对ADO.net 以下观点是错误的
Nhibernate最大优势是在于对于使用者来说尽可能的减少了sql语句的使用,无需使用sql就可以完成很常用的数据操作,你在开发的时候再也不用绞尽脑汁的考虑sql的编写优化这些问题。

因为ADO.net也有着这一个特点


 回复 引用 查看   

#11楼 2007-09-14 13:45 kiler      
@徐少侠

存储过程就不算sql了,你做开发的时候还不是要自己写的,这和写在程序里面的sql不是一个道理。
 回复 引用 查看   

#12楼[楼主] 2007-09-14 13:49 徐少侠      
@kiler

那么一个只能用SQL的东西从性能说已经是不可能被大型项目使用的

同时,那么即使大家都写SQL,NHibernate的优势在哪里呢?

顺便告诉你,使用ADO.net的时候,SQL也不用自己写的。还可以将标准的SQL自动在数据库内生成存储过程并进行调用。这个性能是NHibernate没有的吧?

总之,我需要有人说服我NHibernate有着ADO.net所没有的或者实现起来比他复杂的特性。这样,我们去使用NHibernate的时候才有理由啊
 回复 引用 查看   

#13楼[楼主] 2007-09-14 13:51 徐少侠      
至于使用存储过程和直接使用SQL
对于一个项目的意义可以参考我今后要写的另一个文章。
我首页上已经转载了人家的一篇文章,对那位作者的部分有关存储过程的观点很不赞同。来不及写了。下星期了
 回复 引用 查看   

#14楼 2007-09-14 14:06 henry      
@徐少侠
多体验一下NHibernate的对象化操作,而不是简单对象添加,删除和查询.如果只是这样NHibernate根本没有必要搞得这么复杂.
大家都知道ADO.NET是托管理代码访问数据的入口,虽然在同等代码质量的情况下NHibernate是比不上传统的ADO.NET的.但从另一个角度来目看NHibernate可以保证数据访问代码的质量,这并不是所有开发人员都做得到的.而往往影响性能的确在开发人员编写的代码上.
 回复 引用 查看   

#15楼[楼主] 2007-09-14 14:19 徐少侠      
--引用--------------------------------------------------
henry: @徐少侠
多体验一下NHibernate的对象化操作,而不是简单对象添加,删除和查询.如果只是这样NHibernate根本没有必要搞得这么复杂.
大家都知道ADO.NET是托管理代码访问数据的入口,虽然在同等代码质量的情况下NHibernate是比不上传统的ADO.NET的.但从另一个角度来目看NHibernate可以保证数据访问代码的质量,这并不是所有开发人员都做得到的.而往往影响性能的确在开发人员编写的代码上.
--------------------------------------------------------

上面的话多数都同意
主要提到的功能是说对象化操作

那么在ADO中。
订单row.订单明细Row //属性
订单row.getChildRows(关系对象)
// 就是获得该订单的相关子表内容对象集合

订单明细row.订单Row //属性
订单明细row.getParentRow(关系对象)
订单明细row.getParentRows(关系对象) 就是获得该订单明细的多个父行对象

请具体说明一下NHibernate里面的对象操作是什么?

 回复 引用 查看   

#16楼[楼主] 2007-09-14 14:25 徐少侠      
难道有人认为ADO.net很简单吗?

我在这里敢打赌

凡是喜欢用Hibernate的人,75%不重视数据库设计

75%里面50%不懂ADO.net2.0

他们只懂30%都不到的ADO 2.5

 回复 引用 查看   

#17楼 2007-09-14 14:36 henry      
@徐少侠
订单row.getChildRows(关系对象) 就是获得该订单的相关子表内容对象集合
订单明细row.getParentRow(关系对象) 就是获得该订单明细的父行对象
订单明细row.getParentRows(关系对象) 就是获得该订单明细的多个父行对象
这些问题你都问说明你不了解说NHibernate,我觉得你很无聊.....
同样我可以肯定地答你,如果对Hibernate很了解的人一定非常熟悉ADO.net.
不重视数据库设计的人无论是用Hibernate或ADO.net结果都是一样!
 回复 引用 查看   

#18楼[楼主] 2007-09-14 14:39 徐少侠      
正因为不了解才来问得。

所以请赐教几个代码或者模式我瞧瞧

 回复 引用 查看   

#19楼 2007-09-14 14:44 henry      
虽然我不喜欢NHibernate,有一点相信了解过NHibernate的朋友都知道对象属性的映射原理.如果对于了解NHibernate但又不会用的朋友是应该去补补知识了.
 回复 引用 查看   

#20楼[楼主] 2007-09-14 14:50 徐少侠      
--引用--------------------------------------------------
henry: @徐少侠

同样我可以肯定地答你,如果对Hibernate很了解的人一定非常熟悉ADO.net.
--------------------------------------------------------
上面这个话意思不好

其实很多人都在用NHibernate
但是用的人并不一定很了解,他们可能只是简单的做表影射然后实现基本操作。

另外,在微软的架构中,很快就会有Linq这个东西

举例:
var overdrawnQuery = from account in db.Accounts
where account.Balance < 0
select new { account.Name, account.Address };
从集合对象db.Accounts当中查询帐户对象集合,条件是该帐户的余额小于0

这个答案满意了吧?

 回复 引用 查看   

#21楼[楼主] 2007-09-14 14:52 徐少侠      
--引用--------------------------------------------------
henry: 虽然我不喜欢NHibernate,有一点相信了解过NHibernate的朋友都知道对象属性的映射原理.如果对于了解NHibernate但又不会用的朋友是应该去补补知识了.
--------------------------------------------------------
请具体说明什么叫对象属性映射?

是不是说数据表的字段变成了对象的属性?

如果是的话,那么

int id=订单row.订单ID //这是一个整型属性,ADO自动生成的

算不算呢?
 回复 引用 查看   

#22楼[楼主] 2007-09-14 14:54 徐少侠      
Linq的具体介绍请参考以下连接
http://msdn.microsoft.com/msdnmag/issues/07/06/csharp30/default.aspx?loc=zh
 回复 引用 查看   

#23楼 2007-09-14 15:04 kiler      
@徐少侠

不会ado.net就去用nhibernate肯定是很水的,nhibernate就是基于ado.net做的,不懂ado.net那他nhibernate也用不好。

顺便给你指一个linq的缺点,不能跨数据库。
 回复 引用 查看   

#24楼[楼主] 2007-09-14 15:07 徐少侠      
--引用--------------------------------------------------
kiler: @徐少侠

不会ado.net就去用nhibernate肯定是很水的,nhibernate就是基于ado.net做的,不懂ado.net那他nhibernate也用不好。

顺便给你指一个linq的缺点,不能跨数据库。
--------------------------------------------------------
我的感觉是,我们要更加面向对象

ADO.net这个对象,完成数据库到对象的转换

有了对象以后,我们使用Linq来进行丰富的对象操作

这不就结了啊?

里面没有Hibernate发挥的地方

 回复 引用 查看   

#25楼 2007-09-14 15:09 henry      
@徐少侠
NHibernate支持关联属性映射
如:Employee.Orders Orders可以映射到雇员的订单对象信息,对于one to one,还是one to many等自己配置描述.
为什么MS搞DLinq?显然DLinq最终通过编译器转成Ado.Net代码,按你所说用DLinq的人不是对数据库一无所知?
楼主对Linq认识又有多深?
 回复 引用 查看   

#26楼[楼主] 2007-09-14 15:28 徐少侠      
--引用--------------------------------------------------
henry: @徐少侠
NHibernate支持关联属性映射
如:Employee.Orders Orders可以映射到雇员的订单对象信息,对于one to one,还是one to many等自己配置描述.
为什么MS搞DLinq?显然DLinq最终通过编译器转成Ado.Net代码,按你所说用DLinq的人不是对数据库一无所知?
楼主对Linq认识又有多深?

--------------------------------------------------------
前面回复里面的这些不算关联属性映射吗?

订单row.订单明细Row //属性
订单row.getChildRows(关系对象)
// 就是获得该订单的相关子表内容对象集合

订单明细row.订单Row //属性
订单明细row.getParentRow(关系对象)
订单明细row.getParentRows(关系对象) 就是获得该订单明细的多个父行对象

至于说使用Linq的人对数据库一无所知

这个说来就难了

现在有多少程序员对指针和内存知道很深?对浮点数的内存表示知道很深?
而在10年前说不定这个是人尽皆知的技术
如今的Java程序员又有多少能知道指针?10年后的程序员呢?

知道固然更好,但不知道,只要能利用现有的封装类好好运用,也就可以了。
计算机编码技术在不断的发展,使用一种新技术开始总是为了提高各种效率和质量。但时间长了,有了良好的封装以后。里面的技术就从大众化技术变成了核心技术了

想成为技术天下第一,那就什么都要学。

而对于普通程序员,如果要在最短的时间内获得最大的能力提升。
学习核心技术反而会费很久时间却不能做什么出来

学习一些框架技术并应用之,反而可以快速出项目
比如,在Java那边学习Hibernate的简单使用,就比直接学JDBC更快
好比武打书里面练3年内功和3年招式的区别

自然,长期来看还是内功要紧。一味学快速框架,且不深入框架原理,只知道用的人,10年20年后还是小程序员
而有耐心学核心的人早晚会成为绝世高手

最后回到.net环境
除非最后我能看到NHibernate相对ADO有带来更方便、更快、更直观。
反正就是要有比较有说服力的优势

否则,干吗去学这个东西呢?
省点时间学精ADO.net不好吗?

ps:据说ADO.net 3.0已经Bata了。自然会有新东西体现
另外,以后的数据库如果直接面向对象了。哈哈


 回复 引用 查看   

#27楼 2007-09-14 15:30 kiler      
--引用--------------------------------------------------
微软的ADO.net有着良好的结构。看见很多人在研究ORM。由于对具体的ORM产品没有过多了解,因此感觉这些产品存在的意义似乎不大?

下面表格的比较,试图说明,ADO本身也已经支持对象持久化。如果仅仅是单独一个对象对应一个表或者一行数据,似乎根本不需要使用任何的ORM产品

如果我的论断是对的,那么很多ORM可以洗洗睡了。园子里的某些“兴趣组”也可以关门了
--------------------------------------------------------

你最好也搞清楚一下orm的概念,linq也是一个orm,linq!=ado.net,顺便说一句,ADO本身也不支持对象持久化,ADO只能操作数据库。

顺便再说一句,用。net考虑的最多不是性能,是开发效率。
 回复 引用 查看   

对NHibernate不是很了解,你还拿出来对比,对比的有意义吗?
就比如:我觉得我家的自行车比航空母舰用处大,大家觉得是吗?我家的自行车有车轱辘,车把、铃铛,能骑着去买菜。至于航空母舰,我不太清楚,估计是没自行车用处大。大家如果觉得航空母舰用处大的话,请赐几张图片或动画让我瞧瞧。
有意义吗??

ps:对比的可能有点夸张。
 回复 引用   

#29楼 2007-09-14 15:39 Richie[未注册用户]
虽然两种方案看起来效果好像差不多,但这是两种设计思想
NHibernate是面向对象实践的产物,在面向对象设计中各种问题都有解决方案和最佳实践
typed dataset是什么?MS的平台思想从快速开发向OO方向加强的一个中间产物,千万不要认为在代码中用上object.property就是面向对象了

纯粹使用MS的方案,基本上是表模块的设计方式,系统核心逻辑是绑定在表结构上的;使用NHibernate,就要转向OO方式,否则它的优点也发挥不出来,这样系统的核心逻辑是绑定在对象模型上的,当然表结构的设计也重要,但明显的一点是它完全服务于对象模型,设计的结果跟表模块会有差别

NH在对象关系映射上比较强,各种方式的聚合、组合、关联关系的处理都是按照领域思想提供解决方案,使用到现在唯一感觉弱的地方是对继承的支持
其它一些特性,例如lasy load、batch、cascade、unit of work、cache等,所有这些都要自己去实现,工作量不小,使用性也难说
 回复 引用   

#30楼[楼主] 2007-09-14 15:40 徐少侠      
另外,Linq仅处理对象查询,不涉及对象持久化
对Linq这个东西也就有所了解,下面摘自微软

简单地说,LINQ 是支持以类型安全方式查询数据的一系列语言扩展;它将在代号为“Orcas”的下一个版本 Visual Studio 中发布。待查询数据的形式可以是 XML(LINQ 到 XML)、数据库(启用 LINQ 的 ADO.NET,其中包括 LINQ 到 SQL、LINQ 到 Dataset 和 LINQ 到 Entities)和对象 (LINQ 到 Objects) 等。

还没找到使用Linq来Insert或Update的例子,不过直接查询是可能做到的
 回复 引用 查看   

#31楼[楼主] 2007-09-14 15:47 徐少侠      
--引用--------------------------------------------------
kiler:
你最好也搞清楚一下orm的概念,linq也是一个orm,linq!=ado.net,顺便说一句,ADO本身也不支持对象持久化,ADO只能操作数据库。

顺便再说一句,用。net考虑的最多不是性能,是开发效率。
--------------------------------------------------------
这个说法我喜欢
正因为有了Linq,因此在可以使用Linq的情况下,Hibernate存在的意义是什么?
轻量级解决方案?

Linq本来就不是来替代ADO.net的

用ADO生成对象,用Linq来执行有关对象的查询。

至于说开发效率,用ADO.net慢吗?
我上面的代码后面明确指出,仅用于比较,不是.net开发的最佳代码
在考虑数据绑定和设计时支持后,使用微软现成的开发工具速度是飞快的
 回复 引用 查看   

#32楼[楼主] 2007-09-14 15:50 徐少侠      
--引用--------------------------------------------------
不明白: 对NHibernate不是很了解,你还拿出来对比,对比的有意义吗?
就比如:我觉得我家的自行车比航空母舰用处大,大家觉得是吗?我家的自行车有车轱辘,车把、铃铛,能骑着去买菜。至于航空母舰,我不太清楚,估计是没自行车用处大。大家如果觉得航空母舰用处大的话,请赐几张图片或动画让我瞧瞧。
有意义吗??

ps:对比的可能有点夸张。
--------------------------------------------------------
自行车和航母都是交通工具,有可比性

比如,我出门买菜就不能开航母去

这样就得到了清晰的决策原则

自行车用于解决短途和陆地的交通问题

航母主要用于远程水路,硬在短距离使用叫奢侈!

我发这个随笔的主要目的就是想得出一个决策依据

我们究竟应该在什么时候用NHiernate,什么时候用ADO.net
才能最大限度得发挥这两者的优势。

如果找不出,那我们要NHibernate干吗?
 回复 引用 查看   

#33楼 2007-09-14 15:58 A.Z.[未注册用户]
@徐少侠
个人比较欣赏db4o,至于NHibernate的存在意义,我认同你的观点。
 回复 引用   

#34楼[楼主] 2007-09-14 16:01 徐少侠      
--引用--------------------------------------------------
Richie: 虽然两种方案看起来效果好像差不多,但这是两种设计思想
NHibernate是面向对象实践的产物,在面向对象设计中各种问题都有解决方案和最佳实践
typed dataset是什么?MS的平台思想从快速开发向OO方向加强的一个中间产物,千万不要认为在代码中用上object.property就是面向对象了

纯粹使用MS的方案,基本上是表模块的设计方式,系统核心逻辑是绑定在表结构上的;使用NHibernate,就要转向OO方式,否则它的优点也发挥不出来,这样系统的核心逻辑是绑定在对象模型上的,当然表结构的设计也重要,但明显的一点是它完全服务于对象模型,设计的结果跟表模块会有差别

NH在对象关系映射上比较强,各种方式的聚合、组合、关联关系的处理都是按照领域思想提供解决方案,使用到现在唯一感觉弱的地方是对继承的支持
其它一些特性,例如lasy load、batch、cascade、unit of work、cache等,所有这些都要自己去实现,工作量不小,使用性也难说
--------------------------------------------------------
这个地方感觉你说出了精华

这个观点其实值得大大讨论!!!!!
如今都什么年代了,面向对象啊,同志们
实际上应该是先有对象模型,再有数据库设计。而不是先设计数据库,然后用什么ORM的东西映射到程序里啊!

因此,DataSet里面可能就不完全是数据库表的映射,而是业务对象的映射。
而对于这些可能和数据库实际的表不一致的东西,完全可以使用存储过程来进行复杂的处理。比如我前面提出过的,一个用户实体可能会在数据库里用多张表里的行来表示。

我的基本感觉是,数据集里面的强类型表、行就应该设计成业务对象的类的东西。使用famework2.0的部分类功能扩展实际业务逻辑。
似乎能解决大部分的业务问题了。
而这个模式里似乎不需要任何过多的第三方ORM产品了
除非他有明显的特点并且实现起来不需要程序员过多的干预,否则,和在ADO解决方案里自己写有什么不同哦

PS:ADO.net里面似乎对数据缓冲已经有所考虑的。记得在ASP.net的有关部分曾经见过是否使用缓冲的属性,设个true/false就搞定了。
 回复 引用 查看   

#35楼[楼主] 2007-09-14 16:04 徐少侠      
--引用--------------------------------------------------
A.Z.: @徐少侠
个人比较欣赏db4o,至于NHibernate的存在意义,我认同你的观点。

--------------------------------------------------------
谢谢支持

刚才就想写这个数据库的,可是一下子卡住忘记名字了

免费版,对象数据库的代表

就是一直没空用用
 回复 引用 查看   

#36楼 2007-09-14 16:05 kiler      
@徐少侠

DataSet不等于业务对象,DataSet只是数据库查询结果在内存里面的一个表现形式而已。
 回复 引用 查看   

#37楼 2007-09-14 16:05 A.Z.[未注册用户]
@Richie
表驱动还是业务对象驱动其实这是一个数据建模时考虑的问题。
 回复 引用   

#38楼[楼主] 2007-09-14 16:09 徐少侠      
--引用--------------------------------------------------
kiler: @徐少侠

DataSet不等于业务对象,DataSet只是数据库查询结果在内存里面的一个表现形式而已。

--------------------------------------------------------
使用部分类功能扩展它,或者更原始的我继承下来不就可以了?

反正业务逻辑代码到哪个解决方案里都是要自己写的,多写一个继承的关键字不浪费时间的。
但是这样一来,所有需要和数据库交互的业务对象就自动拥有了和数据库交互的能力。

意下如何?
 回复 引用 查看   

#39楼 2007-09-14 16:39 cmsoft[未注册用户]
建议博主去看看scott gu的Linq to sql系列文章就知道how to insert or update
 回复 引用   

#40楼 2007-09-14 16:40 杨义金      
不懂ORM就不要随便发言,尽在这里瞎猜,谁用过ORM做过项目,谁就有权发言。
个人认识的深度,不代表ORM产品和项目的深度。
 回复 引用 查看   

#41楼[楼主] 2007-09-14 16:52 徐少侠      
--引用--------------------------------------------------
cmsoft: 建议博主去看看scott gu的Linq to sql系列文章就知道how to insert or update
--------------------------------------------------------


Linq这么强大啊?

谢谢

那个老大的Blog的确好。就是平时老不去看,惭愧。
 回复 引用 查看   

#42楼[楼主] 2007-09-14 16:57 徐少侠      
--引用--------------------------------------------------
A.Z.: @Richie
表驱动还是业务对象驱动其实这是一个数据建模时考虑的问题。

--------------------------------------------------------


但是貌似业务驱动更OO一些。

并且考虑到扩展的话,表早晚是会有变化的。业务对象也会变

业务对象的改变可以用类的扩展来解决

表的变化可以用存储过程、视图等来隔离。

如果选择表驱动,那么很可能在业务变化的时候要么修改原始表(也不轻松吧?),要么依然回到表和业务分离的路子上。
 回复 引用 查看   

#43楼[楼主] 2007-09-14 16:58 徐少侠      
--引用--------------------------------------------------
杨义金: 不懂ORM就不要随便发言,尽在这里瞎猜,谁用过ORM做过项目,谁就有权发言。
个人认识的深度,不代表ORM产品和项目的深度。

--------------------------------------------------------
陈恳希望有经验的同志大哥来指教一二阿。
 回复 引用 查看   

#44楼 2007-09-14 17:11 henry      
在完全支持Linq的地方NHibernate就没有用处了吧?
到底现在Linq是不是真的利害到可以扼杀一切还没有定断,我看来现版本的Linq在数据操远达到SQL优雅高效,唯的好处就是借助于编译器实现检测(不过的确可以节省很大调试成本,但对于其编写简洁性有所保留),如果编译器直接直入SQL并根据查询返回动太对象类型那这个时候Linq就走一边去了.任何事物都在发展的别看了一个东西有些甜头就把别东西看成一坨屎......
 回复 引用 查看   

#45楼[楼主] 2007-09-14 17:52 徐少侠      
看来在目前情况下,对象查询以及操作是Hibernate的强项
自己去实现是需要写不少代码了

尚没有普及的Linq等等就先不做考虑

似乎ADO可以完成对象映射,但是操作就没什么优势
而Hibernate可以提供OO方式的丰富的对象操作

至于以后ADO3.0什么的,今天就拿来说话似乎不合适

恩,这个主题的结论似乎快出来了。
 回复 引用 查看   

#46楼 2007-09-14 18:02 A.Z.[未注册用户]
这个没有什么好争的,普通级别的项目没有复杂的表,有复杂结构表的项目对数据处理响应速度要求会很高,而NHibernate的入门需要做太多繁杂的事情,要精通还要去研究很多细节,真正可以在上面把握住性能问题的实际项目是少是又少,不过如果有人已经大费周章搭好环境后让我在上面敲几行代码就把所有事情搞定,也不是一件坏事,本来NHibernate就是效仿java的实现,java又是一个过于繁琐的东西,所以才会有这样的产物来减少数据库和对象间的外在偶合关系,但是又引入了很多新的规则,比如hql.还是这句话:可以不接触尽量不要接触,实在不行就顺其道偷偷懒。
 回复 引用   

徐少侠TX应该先弄明白以下问题
何谓持久化对象,为何要持久化对象?
何谓ORM,在持久化对象的时候为什么要使用ORM?
不过首先应该先问问自己,是不是在用OO的方式在设计,在编程。如果不OO,何必要ORM呢?

 回复 引用 查看   

#48楼 2007-09-14 22:11 idior      
无语,看到这种文章真让人心寒!
http://www.cnblogs.com/idior/archive/2006/06/07/419999.html
 回复 引用 查看   

微软的强类型DataSet配合TableAdapter,个人觉得已经可以算一个ORM了。
 回复 引用   

#50楼 2007-09-15 09:43 JoeLee[未注册用户]
服了你们楼上的了.费那么多口舌教育一个不懂事的孩子做什么.
我就一句话.博主SB.鉴定完毕.
 回复 引用   

#51楼 2007-09-15 14:26 镜涛      
还是向往linq
 回复 引用 查看   

#52楼 2007-09-15 23:40 wokexi[未注册用户]
--引用--------------------------------------------------
JoeLee: 服了你们楼上的了.费那么多口舌教育一个不懂事的孩子做什么.
我就一句话.博主SB.鉴定完毕.
--------------------------------------------------------
虽然狠了点,但是也是我想说的。
 回复 引用   

从ADO.NET到NHibernate,我也有和LZ类似的疑惑:.Net 2.0中的typed dataset已经很强大很对象话了,为什么还要弄一个NHibernate出来?后来经过自己一段时间的理解,我觉得有以下几个可以考虑的地方:
1、typed dataset是从数据库到类的,也就是说在开发的过程中先数据库后对象。而NHibernate则不同,既可以先数据库再对象,也可以先对象后数据库。尤其是后点,这才是符合OO设计的本质要求。
2、个人感觉typed dataset是一种快餐式的O/R Mapping。往往为了满足一个小小的映射,却生成很多冗余的代码。而NHibernate不存在这种问题,选择NHibernate,你会觉得你不是一个简单的程序员,甚至是一个艺术家。

总之如果是做一些简单的项目我会选择typed dataset,如果选择稍微负责的项目,我会用NHibernate,甚至会根据项目的要求自己写一个ORM架构。
 回复 引用   

#54楼 2007-09-16 18:02 光影传说      
大家不要再争论了,如果大家关注一下我的Blogs,我会慢慢的把两都之间的区别分开的,用ORM关键在于封装,是业务层的封装,再用MSDTC之后,你就会发现威力所在了。业务复杂的,面向数据的解决方案可能很难理清楚。如果ORM仅仅用在数据存取方面,可就有些大材小用了。就如现在公司Java阵营的说我的框架太复杂,培训人的成本太高,因为他们没有深入其中,不会发现其中的核心。所以呢,大家不要再争论为什么要需要ORM。
.Net下的ORM常用的有2个,一个NHibernate一个是IBATIS,如果我选择的话,我会选择NHibernate,但是IBATIS偏向于面向数据,易于上手,如果原来项目是基于数据库设计的话,可以转换到上面来。我的项目里用的ORM是自己写的,启动时间比NHibernate稍微晚一点点,业务处理的时候类似于NHibernate,查询的时候可以支持类似于IBATIS的查询,整个框架无缝集成,特别是与业务层的集成和数据适配层的集成。
 回复 引用 查看   

#55楼[楼主] 2007-09-17 09:02 徐少侠      
@snowwaft

使用强类型数据集也可以做到先对象后数据库设计
其实先决定哪个不就是人的思想吗?

至于冗余代码,用不上的才是没有用的.那么只要充分利用了就不会浪费

另外,代码是不是简洁并不是决定使用哪种技术的主要决策依据

上面我已经有了一个结论

ADO不支持更好的对象操作,因此不适合在这方面有需要的项目.
 回复 引用 查看   

#56楼[楼主] 2007-09-17 10:09 徐少侠      
@光影传说
支持
如果ORM仅仅用在数据存取方面,可就有些大材小用了。

ORM的长处就在于对象操作



 回复 引用 查看   

看来作者对面象对象的认识,还处在文盲阶段。
 回复 引用   

文章,及评论回复逻辑混乱
 回复 引用   

更关键问题:博客园还将这样的文章推荐其首页?真是捉襟见肘
 回复 引用   

sorry ,说文盲太过了,应该是门外汉。
 回复 引用   

看样子又是上海这个环境培养出来的程序员,缺少必要的对软件认识的熏陶。
 回复 引用   

#62楼 2007-09-17 11:20 聂锋      
似乎概念不同。。
 回复 引用 查看   

#63楼 2007-09-17 19:17 Spring.Cheung      
有了Linq,你又怎样?难道还要等个2、3年才能支持Oracle,MySql?
 回复 引用 查看   

#64楼[楼主] 2007-09-18 11:03 徐少侠      
Linq和任何数据库产品无关
Linq是一个针对对象的查询和操作

在我的方案中使用存储过程封装数据库的非面向对象特性
从存储过程出来的数据唯一对应业务实体
在应用程序内部使用Linq或者其它的对象操作方案进行操作
力图实现应用程序的数据库无关性。

刚好昨天另外写了一篇有关这个东西的文章。
请帮忙看看
 回复 引用 查看   

#65楼 2007-09-18 13:52 A.Z.[未注册用户]
@Spring.Cheung
等用什么数据库你有发言权的时候再来抱怨为什么dlinq支持sql2k5
 回复 引用   

#66楼 2007-10-22 17:53 aaa2000[未注册用户]
看来作者对面象对象的认识,还处在文盲阶段。
-----------------------------------------
认同,由于我们接受的教育一直是面象数据,没有OO观念的程序员一般是这样开发的:
一、收集用户需求,画出流程图或其他相关文档。
二、根据需求设计相关的数据表。
三、写代码。

所以NHibernate对他们完全是多余的,直接写SQL语句更好。
 回复 引用   

呵呵 今天又看到这篇老帖子
我目前还比较倾向于dataaccess class+代码生成器的架构
 回复 引用 查看   

#68楼 2009-01-07 19:21 施杨      
帖子很可笑。
 回复 引用 查看   

#69楼 2009-01-10 00:20 Flicker      
无知者无畏
 回复 引用 查看