Fork me on GitHub
C#总结2012
Moon.ORM技术全攻略

 一.绪论

      本文主要是针对Moon.ORM的技术的讨论及其使用使用指导.如有其它疑问,请留言.本文从实际出发解析Moon.ORM.(技术群:21696534)

关于实体框架
       微软不久前开源了EF5.0,获取了其代码发现并不能编译,大致看了其代码.优雅便捷可谓正统,但其实战性仍待提高.

       1)Linq不能为我们生成理想的sql,而且linq自身的性能有损失.这是EF不得不面主要的问题.没有完美的东西只有平衡点--没有银弹

       2)linq不能解决复杂度较高的查询;而且微软视图忽视数据库,但这是绝对不可能的.大家自己去思考. 

       3)多数据库多数据源问题解决较为麻烦;

       4)仅仅支持.net 4.5,目前无法在windows 2003上运行. 

EF 的优点诸多不必多说.    Linq的优缺点似乎也成了EF的优缺点之一.微软想通过Linq让我们以一种面向数据对象的方式来思考,及持久化他们的数据.可是我们可想想数据库的中 的记录难道就不是对象了?Linq给人以优雅和便捷我想这是他明显的优势,然后就是匿名对象在其中发挥的重要作用.

...

 二.Moon.ORM的特色及优势

      ----但凡众多的智慧都是及其简单的,但不为人所知.这也是Moon.ORM的主要特色:大道至简.

      1.高性能是Moon.ORM优势之一,也是我架构它的主要目的之一,如以前我说的那样,是为了弥补项目中遇到的性能问题而设计.可以说对于整个框架数据 处理上采用了纯的ADO.NET进行封装同时结合了EMIT达到快速生成实体的目的(当然到时候也可以用4.0的代码生成器完成纯ADO.NET的开 发).我不得不承认linq和lambda语句带来的优雅,但同时我们需要承认linq的局限性.或许有人说可以通过手段进行一些弥补,如有人以提高 linq性能来写文章一样,但我们需要承认两个事实,每次对linq的系统识别后才能进行优化,也就是说,linq的天性决定有性能损失.再次linq不 是银弹,因为负责的场合linq几乎是做不到的,何况linq生成的sql不一定是你真正要的.(注意:我不是敌对linq,而是说实话,正如曾说:实际开发中没有银弹,只有平衡点,适合需求能解决实际情况的架构那就够了)而且我也没有必要再去写一个框架,做一个类似Nhibernate,或者实体框架的东西.做东西我一直认为需要做一个能有自我的特色和优势.

      2.易用性,我想用过Moon.ORM的应该可以知道这点.配置简单,智能感知,代码生成器的辅助,会sql就可会用Moon.

      3.多数据库多数据源支持.在同一个项目中我们需要处理这种情况时,Moon.ORM是你最好的选择.如你系统默认为MSSQL,现在要同时使用 MYSQL,你只需要实例化一个引擎就可以.DBFactory.GetEntity<Person> (pjy_AdminRoleTable.RoleID.BiggerThan(0),new MYSQL("连接字符串"));当然你可以把引擎做成全局的.

      4.语法糖功能.个人使用的结果是大概能满足我实际需求的70%以上的功能.

      5..NET 2.0原生支持,这个就不用说了.

      6.数据库转变问题,如果你发现你有一天你的数据库需要从mysql转变到mssql,你只需要转变你的配置文件即可.(当然sql语法差异的问题,你需要自己注意了,如果你在用原生的sql进行操作时).

三.维护问题.

      有人曾说'都没源代码,所以我不能用'.我不能自比微软,但我们可以换一个位置想想:知道.net framework 3.5 sp1中的bug吗?微软的库中也会有bug信吗?Moon.ORM标准版,一律免费使用(包括API文档等)和群技术支持.对于企业用户我会提供专门的 服务和技术支持以及更加美观强大易用的企业版Moon.orm代码生成器工具及技术培训资料.

四.同类产品对比.

五. 绝对性能优势

      3.9版本后已将查询性能提升到了极致≈纯sql查询的性能.

六.技术指导(主要提供绝大部分的情况,供参考,具体请看API文档)

      一.查询操作.

        1.查询一条记录(一个实体)

            Administrator newUser=DBFactory.GetEntity<Administrator>(AdministratorTable.ID.Equal(userID).And(
AdministratorTable
.Age.Equal(12)));

        2.查询多条记录(多个实体)

            var list=DBFactory.GetEntities<Administrator>(AdministratorTable.ID.BiggerThan(9));

        3.嵌套查询(codeID作为外键指向Administrator的ID)

            var list=DBFactory.GetEntities<Administrator>(AdministratorTable.ID
                                                          .Equal(AttachmentTable.codeID.SelectWhere(AttachmentTable.fileName.Equal("ee.txt"))));

        4.对于复杂的多表查询,使用代码生成器,把你的sql复制过去,然后它帮助你生成实体,最终

            NewOBJ newUser=DBFactory.GetEntity<NewOBJ >(sql语句);

        5.单一数据查询.

            string userName=DBFactory.GetOneField<string>(AdministratorTable.UserName,AdministratorTable.ID.BiggerThan(0));

             (注意可能报异常,比如查出来的数据为DBNull). 

        6.记录条数查询.

           long count=DBFactory.GetCount(AdministratorTable.UserName,AdministratorTable.ID.BiggerThan(0)); 

        7. 返回其他的格式.可以参考API看DB

         (调用方法如:DBFactory.DefaultDB.GetDataSet("sql语句");)DefaultDB的类型为DB,其API可看帮助文档; 

 

 

        8. 查询单一字段.
       var userName=DBFactory.GetOneField<string>(UserTable.UserName,UserTable.Age.Equal(12).And(UserTable.Tel.Equal("qsmy")));
       

        9.指定字段对象查询.

       var user=DBFactory.GetEntity<User>(UserTable.Age+UserTable.UserName,UserTable.ID.Equal(12));

        10.复杂查询功能.Moon给出了三种解决方案.

          1.代码生成器生成实体,把您的sql语句(无论多么复杂)放入代码生成器,它会自动给你生成强类型实体,如第4条说的.

          2.智能实体,不需要代码生成器,如下

             var list=DBFactory.GetIntelligentEntity("select * from [User]");
            Console.WriteLine(list[index]["username"].To<string>());(注意字段全是小写)

            

            var user=DBFactory.GetIntelligentEntity("select * from [User] where age>3");
            Console.WriteLine(user["username"].To<string>());

          3.动态编译实体,同样不需要代码生成器(Moon5.0会与大家相见)

           

            
var list=DBFactory.GetAutoEntities("相当复杂的一个sql查询语句","自定义类名");
for(var a in list){
int count=a.Count;
string country=a.Country;
}

  

    

 
      二.数据添加操作.
            Administrator admin=new Administrator();
            admin.UserName="秦仕川"+DateTime.Now;
            admin.Password="qsmy";
            //开启事务操作
            admin.StartTransaction(true);
            //返回主键值
            int userID=Convert.ToInt32(DBFactory.Add(admin));
      三.数据删除操作.
            //返回删除的条数
            long count=DBFactory.DeleteWhen(AdministratorTable.ID.BiggerThan(0));
      四.数据修改操作. 
            Administrator admin=new Administrator();
            admin.UserName="秦仕川"+DateTime.Now;
            admin.Password="qsmy";
            admin.SetOnlyMark(AdministratorTable.ID.BiggerThan(0));
            //开启事务操作
            admin.StartTransaction(true);
            //返回主键值
            DBFactory.Update(admin);

 

七.需要明白的Moon.ORM设计前提

   1.对于数据库的设计,每一个表必须要有主键;

   2.由业务决定逻辑的主键设计方案是错误的,所以主键是不能被业务牵制的,因为业务是变动的.Moon.ORM需建立独立于业务

之外的.所以主键的设计MOON选择的是guid或者自增的情况(建议用自增的方式). 

 

八.使用说明

 

   使用说明:代码生成器及使用说明

 

1.下载代码生成器(上面,最新版本下载)

    2.修改代码生成器的配置文件.如下图.(如果是mysql见 6.使用说明)

    3.运行代码生成器生成实体

 

用代码生成器生成实体层. 加入你要做的项目中.
(可以把这段代码文件.cs复制到项目中,也可引用编译文件.dll)
 

 

    4.实际项目中引入Moon.Orm和上面生成的.cs或.dll

 

 
Moon 4.1及代码生成器下载:
技术群:21696534

/Files/humble/MoonOrm5.7z 

一周的学习结束了。C#的学习也算是有了一个终结,这里面的知识点太多,我都有些慌乱了。在学习的时候呢,每天学点,再加上及时的练习感觉还可以,可结束之后,发现学过的几乎都忘了,有些难以理解的还须重新整理。从C#的简单语法到高级语法,最难掌握的应该也就是高级语法了。有点让人晕。

一:C#变量

分为值类型和引用类型

值类型有:int ,long,byte,float,double,eumn,char,bool,struct

引用类型有:string,类,数组,借口,delegate

在这一部分尤其需要注意的是数据类型之间的转换。

1.显示转换

大类型数据赋值给小类型数据

类型A  a = (类型A) b;

2.隐式转换

小类型数据赋值给大类型数据,系统会进行隐式转换

3.通过Convert.ToType()转换

二,C#函数

1.函数的定义

[访问修饰符] {static} 返回值类型   函数名 ([参数列表])

{

  //函数体

}

2.函数参数的类型

①值传递

②址传递

③out传递

传递的是地址,要求没有初值

④params可变常量

  (1)变量的类型是数组类型,在传递的时候,可以是数组,也可以是一些列元素。

   (2)一般情况下,params声明的参数在最后。

View Code

三,C#面向对象

[访问修饰符] class 类名
    {
     //类体
    }

 在程序里面有且只能有一类包含Main方法

创建对象:
    类名 对象名 = new 类名();

由于今天有些晚了,就先到这里了,改天继续吧!!!

 

 

 

 

 

 

 

 

 
分类: C#

6天通吃树结构—— 第四天 伸展树

 

 

      我们知道AVL树为了保持严格的平衡,所以在数据插入上会呈现过多的旋转,影响了插入和删除的性能,此时AVL的一个变种

伸展树(Splay)就应运而生了,我们知道万事万物都遵循一个“八二原则“,也就是说80%的人只会用到20%的数据,比如说我们

的“QQ输入法”,平常打的字也就那么多,或许还没有20%呢。

 

一:伸展树

 1:思想

    伸展树的原理就是这样的一个”八二原则”,比如我要查询树中的“节点7”,如果我们是AVL的思路,每次都查询“节点7”,那么当这

棵树中的节点越来越多的情况下就会呈现下旋,所以复杂度只会递增,伸展树的想法就是在第一次查询时树里面会经过一阵痉挛把

“节点7”顶成“根节点”,操作类似AVL的双旋转,比如下图:

当我们再次查询同样的”数字7“时,直接在根节点处O(1)取出,当然这算是一个最理想的情况,有时痉挛过度,会出现糟糕的”链表“,

也就退化了到O(N),所以伸展树讲究的是”摊还时间“,意思就是说在”连续的一系列操作中的平均时间“,当然可以保证是log(N)。

 

2:伸展方式

    不知道大家可否记得,在AVL中的旋转要分4个情况,同样伸展树中的伸展需要考虑6种情况,当然不考虑镜像的话也就是3种情况,

从树的伸展方向上来说有“自下而上”和“自上而下"的两种方式,考虑到代码实现简洁,我还是说下后者。

 

<1> 自上而下的伸展

      这种伸展方式会把树切成三份,L树,M树,R树,考虑的情况有:单旋转,“一字型”旋转,“之字形”旋转。

①: 单旋转

从图中我们可以看到,要将“节点2”插入到根上,需要将接近于“节点2”的数插入到根上,也就是这里的“节点7”,首先树被分成了3份,

初始情况,L和R树是“空节点”,M是整棵树,现在需要我们一步一步拆分,当我们将“节点2”试插入到“节点7”的左孩子时,发现“节点7”

就是父节点,满足“单旋转”情况,然后我们将整棵树放到“R树”中的left节点上,M此时是一个逻辑上的空节点,然后我们将R树追加到

M树中。L树追加到M的左子树中,最后我们将“节点2”插入到根节点上。说这么多有点拗口,伸展树比较难懂,需要大家仔细品味一下。

 

②: 一字型

一字型旋转方式与我们AVL中的“单旋转”类似,首先同样我们切成了三份,当我们"预插入20时”,发现20的“父节点”是根的右孩子,

而我们要插入的数字又在父节点的右边,此时满足”一字型“旋转,我们将7,10两个节点按照”右右情况”旋转,旋转后“节点10"的

左孩子放入到L树的right节点,"节点10”作为中间树M,最后将20插入根节点。

③: 之字形

 

之字形有点类似AVL中的“双旋转”,不过人家采取的策略是不一样的,当我们试插入“节点9”,同样发现“父节点”是根的右儿子,并且

“节点9”要插入到父节点的内侧,根据规则,需要将“父节点10”作为M树中的根节点,“节点7”作为L树中的right节点,然后M拼接L和R,

最后将节点9插入到根上。

 

3:基本操作

①:节点定义

我们还是采用普通二叉树中的节点定义,也就没有了AVL那么烦人的高度信息。

复制代码
 1     public class BinaryNode<T>
 2     {
 3         // Constructors
 4         public BinaryNode(T theElement) : this(theElement, null, null) { }
 5 
 6         public BinaryNode(T theElement, BinaryNode<T> lt, BinaryNode<T> rt)
 7         {
 8             element = theElement;
 9             left = lt;
10             right = rt;
11         }
12 
13         public T element;
14 
15         public BinaryNode<T> left;
16 
17         public BinaryNode<T> right;
18     }
复制代码

②:伸展

     这里为了编写代码方便,我采用的是逻辑nullNode节点,具体伸展逻辑大家可以看上面的图。

复制代码
 1         #region 伸展
 2         /// <summary>
 3         /// 伸展
 4         /// </summary>
 5         /// <param name="Key"></param>
 6         /// <param name="tree"></param>
 7         /// <returns></returns>
 8         public BinaryNode<T> Splay(T Key, BinaryNode<T> tree)
 9         {
10             BinaryNode<T> leftTreeMax, rightTreeMin;
11 
12             header.left = header.right = nullNode;
13 
14             leftTreeMax = rightTreeMin = header;
15 
16             nullNode.element = Key;
17 
18             while (true)
19             {
20                 int compareResult = Key.CompareTo(tree.element);
21 
22                 if (compareResult < 0)
23                 {
24                     //如果成立,说明是”一字型“旋转
25                     if (Key.CompareTo(tree.left.element) < 0)
26                         tree = rotateWithLeftChild(tree);
27 
28                     if (tree.left == nullNode)
29                         break;
30 
31                     //动态的将中间树的”当前节点“追加到 R 树中,同时备份在header中
32                     rightTreeMin.left = tree;
33 
34                     rightTreeMin = tree;
35 
36                     tree = tree.left;
37                 }
38                 else if (compareResult > 0)
39                 {
40                     //如果成立,说明是”一字型“旋转
41                     if (Key.CompareTo(tree.right.element) > 0)
42                         tree = rotateWithRightChild(tree);
43 
44                     if (tree.right == nullNode)
45                         break;
46 
47                     //动态的将中间树的”当前节点“追加到 L 树中,同时备份在header中
48                     leftTreeMax.right = tree;
49 
50                     leftTreeMax = tree;
51 
52                     tree = tree.right;
53                 }
54                 else
55                 {
56                     break;
57                 }
58             }
59 
60             /* 剥到最后一层,来最后一次切分 */
61             //把中间树的左孩子给“左树”
62             leftTreeMax.right = tree.left;
63 
64             //把中间树的右孩子给“右树”
65             rightTreeMin.left = tree.right;
66 
67             /* 合并操作 */
68             //将头节点的左树作为中间树的左孩子
69             tree.left = header.right;
70 
71             //将头结点的右树作为中间树的右孩子
72             tree.right = header.left;
73 
74             return tree;
75         }
76         #endregion
复制代码

③:插入

插入操作关键在于我们要找到接近于”要插入点“的节点,然后顶成“根节点”,也就是上面三分图中的最后一分。

复制代码
 1 #region 插入
 2         /// <summary>
 3         /// 插入
 4         /// </summary>
 5         /// <param name="Key"></param>
 6         public void Insert(T Key)
 7         {
 8             if (newNode == null)
 9                 newNode = new BinaryNode<T>(default(T));
10 
11             newNode.element = Key;
12 
13             if (root == nullNode)
14             {
15                 newNode.left = newNode.right = nullNode;
16 
17                 root = newNode;
18             }
19             else
20             {
21                 root = Splay(Key, root);
22 
23                 int compareResult = Key.CompareTo(root.element);
24 
25                 if (compareResult < 0)
26                 {
27                     newNode.left = root.left;
28 
29                     newNode.right = root;
30 
31                     root.left = nullNode;
32 
33                     root = newNode;
34                 }
35                 else
36                     if (compareResult > 0)
37                     {
38                         newNode.right = root.right;
39 
40                         newNode.left = root;
41 
42                         root.right = nullNode;
43 
44                         root = newNode;
45                     }
46                     else
47                         return;
48             }
49 
50             newNode = null;
51         }
52         #endregion
复制代码

④:删除

  删除操作也要将节点伸展到根上,然后进行删除,逻辑很简单。

复制代码
 1  #region 删除
 2         /// <summary>
 3         /// 删除
 4         /// </summary>
 5         /// <param name="Key"></param>
 6         public void Remove(T Key)
 7         {
 8             BinaryNode<T> newTree;
 9 
10             //将删除结点顶到根节点
11             root = Splay(Key, root);
12 
13             //不等于说明没有找到
14             if (root.element.CompareTo(Key) != 0)
15                 return;
16 
17             //如果左边为空,则直接用root的右孩子接上去
18             if (root.left == nullNode)
19             {
20                 newTree = root.right;
21             }
22             else
23             {
24                 newTree = root.left;
25 
26                 newTree = Splay(Key, newTree);
27 
28                 newTree.right = root.right;
29             }
30             root = newTree;
31         }
32         #endregion
复制代码

 

总的运行代码如下:

View Code

伸展树可以总结成一幅图:

 
posted on 2012-08-05 00:43  HackerVirus  阅读(193)  评论(0编辑  收藏  举报