.NET ORM 的 “SOD蜜”--零基础入门篇

PDF.NET SOD框架不仅仅是一个ORM,但是它的ORM功能是独具特色的,我在博客中已经多次介绍,但都是原理性的,可能不少初学的朋友还是觉得复杂,其实,SOD的ORM是很简单的。下面我们就采用流行的 Code First的方式,一步步来了解下。

一、准备工作

1.1,添加SOD包引用

首先建立一个控制台项目,并使用程序包管理器添加PDF.NET SOD的程序引用:

PM> Install-Package PDF.NET

更多详细使用信息说明,请参考nuget 网站说明 https://www.nuget.org/packages/PDF.NET/

1.2,配置数据连接

新建一个控制台项目,添加一个应用程序配置文件,增加一个数据库连接配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionStrings>
        <add name="local" connectionString="Data Source=.;Initial Catalog=LocalDB;Integrated Security=True" providerName="SqlServer" />
    </connectionStrings>
</configuration>

确保你本地有SqlServer数据库,并且版本是2005以上,有一个数据库名字是 LocalDB,当然你可以修改成你实际的连接字符串。

之后,我们的查询示例,都将采用这个连接配置。

1.3,定义实体类

我们将使用用最常见的用户登录来举例,这里需要一个用户实体类,假设它的定义是下面这个样子的:

public class User : EntityBase
    {
        public User()
        {
            TableName="Tb_User";
            IdentityName = "UserID";
            PrimaryKeys.Add("UserID");
        }

        public int ID
        {
            get { return getProperty<int>("UserID"); }
            set { setProperty("UserID", value); }
        }

        public string Name
        {
            get { return getProperty<string>("Name"); }
            set { setProperty("Name", value, 50); }
        }

        public string Pwd
        {
            get { return getProperty<string>("Pwd"); }
            set { setProperty("Pwd", value, 50); }
        }

        public DateTime RegistedDate
        {
            get { return getProperty<DateTime>("RegistedDate"); }
            set { setProperty("RegistedDate", value); }
        }

    }

1.4,添加查询对象的数据上下文

在项目中添加一个 LocalDbContext.cs 文件,文件中添加如下代码,以便检查表 Tb_User 是否存在,如果不存在,则自动创建一个:

/// <summary>
 /// 用来测试的本地SqlServer 数据库上下文类
 /// </summary>
  public class LocalDbContext : SqlServerDbContext
  {
      public LocalDbContext()
          : base("local")
      {
          //local 是连接字符串名字
      }

      #region 父类抽象方法的实现

      protected override bool CheckAllTableExists()
      {
          //创建用户表
          CheckTableExists<User>();
          return true;
      }

      #endregion
   }

本例中使用SqlServer 作为查询示例,所以该处使用 SqlServerDbContext 抽象类为基类。

1.5,创建数据库表

OK,基本准备就绪,现在Main 方法里面可以写下面的代码开始工作了:

LocalDbContext context = new LocalDbContext();//自动创建表

准备工作全部完成,运行这一句代码,之后查看SqlServer管理工具,发现表 Tb_User 已经创建了。

二、ORM之增,删,改

SOD框架的ORM功能跟通常的ORM框架不同,SOD框架的实体类上并没有数据查询和持久化的方法,所以SOD的实体类是“非常纯粹的”实体类,你可以把它看作是一个数据容器,或者用来当作DTO,ViewModel使用,有关这个话题更详细的阐述,请看这篇文章:《DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架》。

在进行真正的数据查询之前,得先有数据,所以我们先测试数据的增删改。

2.1,删除数据

首先删除之前的测试数据,可以采用OQL进行批量数据删除:

int count = 0;

//删除 测试数据-----------------------------------------------------
User user = new User();
OQL deleteQ = OQL.From(user)
                .Delete()
                .Where(cmp => cmp.Comparer(user.ID, ">", 0)) //为了安全,不带Where条件是不会全部删除数据的
             .END;
count= EntityQuery<User>.ExecuteOql(deleteQ, context.CurrentDataBase);

这里将用户ID 大于0的数据全部删除了,框架内置了数据安全机制,不会随意删除全部数据,所以为了清除全部数据,采用了上面的方法。

2.2,增加数据

方式1,采用DbContext 的Add 方法:

            count = 0;
            User zhang_san = new User() { Name = "zhang san", Pwd = "123" };
            count += context.Add<User>(zhang_san);//采用 DbContext 方式插入数据

方式2,采用OQL:

            User li_si = new User() { Name = "li si", Pwd = "123" };
            OQL insertQ= OQL.From(li_si)
                            .Insert(li_si.Name);//仅仅插入用户名,不插入密码

OQL还需EntityQuery 对象配合,才可以执行,继续看下面的代码:

 AdoHelper db = MyDB.GetDBHelperByConnectionName("local");
 EntityQuery<User> userQuery = new EntityQuery<User>(db);
 count += userQuery.ExecuteOql(insertQ);

下面是结果图:

方式3,直接EntityQuery 插入实体类:

 User zhang_yeye = new User() { Name = "zhang yeye", Pwd = "456" };
 count += EntityQuery<User>.Instance.Insert(zhang_yeye);//采用泛型 EntityQuery 方式插入数据

2.3,修改数据:

方式1,采用 DbContext 方式更新数据

 li_si.Pwd = "123123";
 count = context.Update<User>(li_si);//采用 DbContext 方式更新数据

方式2,采用OQL方式更新指定的数据

 li_si.Pwd = "123456";
OQL updateQ= OQL.From(li_si)
                .Update(li_si.Pwd) //仅仅更新密码
             .END;
count += EntityQuery<User>.Instance.ExecuteOql(updateQ);//采用OQL方式更新指定的数据

方式3,采用泛型 EntityQuery 方式修改数据

  li_si.Pwd = "888888";
  count += EntityQuery<User>.Instance.Update(li_si);//采用泛型 EntityQuery 方式修改数据

三、ORM之数据查询

前面增删改数据完成了,现在有了测试数据,我们可以来进行ORM的数据查询测试了,这里使用用户登录的例子来测试,框架提供了6种数据查询方式。

3.1,最简单的方法

假设前端直接传递了一个 User 实体类对象,中间设置了用户名和密码,现在有一个登录方法使用该对象,该方法详细内容如下所示:

       /// <summary>
        /// 使用用户对象来登录,OQL最简单最常见的使用方式
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool Login(User user)
        {
            OQL q = OQL.From(user)
                .Select()
                .Where(user.Name, user.Pwd) //以用户名和密码来验证登录
            .END;

            User dbUser =q.ToEntity<User>();//ToEntity,OQL扩展方法
            return dbUser != null; //查询到用户实体类,表示登录成功
        }

这里我们使用了SOD框架的ORM查询语言--OQL,它的结构非常类似于SQL,你可以认为OQL就是对象化的SQL语句。

OQL表达式采用 .From.....END 的语法,对象的链式方法调用,只要敲点出来的就是正确的,这样没有SQL基础的同学也可以很快掌握该查询语法,也能马上作数据开发。

注意:在本例中,使用了OQL的扩展方法,因此需要引用下面的名字空间:

using PWMIS.Core.Extensions;

如果不使用扩展方法,可以采用泛型EntityQuery 的方法,请看下面的示例。

3.2,使用 OQLCompare 对象的 EqualValue 相等比较方式

        /// <summary>
        /// 使用用户对象来登录,但是使用 OQLCompare 对象的 EqualValue 相等比较方式
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool Login1(User user)
        {
            OQL q = OQL.From(user)
                 .Select(user.ID) //仅查询一个属性字段 ID
                 .Where(cmp => cmp.EqualValue(user.Name) & cmp.EqualValue(user.Pwd))
              .END;

            User dbUser = EntityQuery<User>.QueryObject(q);
            return dbUser != null; //查询到用户实体类,表示登录成功
        }

跟例1一样,这里也要求user 对象的Name和Pwd属性必须事先有值。本例没有使用OQL的扩展方法。

3.3, EntityQuery 泛型查询方法

本例只是对例子1做了下改进,重点在于登录方法的参数不是用户对象,而是名字和密码参数。

       /// <summary>
        /// 使用用户名密码参数来登录,采用 EntityQuery 泛型查询方法
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public bool Login2(string name, string pwd)
        {
            User user = new User()
            {
                Name = name,
                Pwd = pwd
            };

            OQL q = OQL.From(user)
                .Select(user.ID)
                .Where(user.Name, user.Pwd)
            .END;
            User dbUser = EntityQuery<User>.QueryObject(q);

            return dbUser != null; //查询到用户实体类,表示登录成功
        }

4,使用OQLConditon 对象为查询条件

       /// <summary>
        /// 使用用户名密码参数来登录,使用早期的实例化OQL对象的方式,并使用OQLConditon 对象为查询条件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public bool Login3(string name, string pwd)
        {
            User user = new User();
            OQL q = new OQL(user);
            q.Select(user.ID).Where(q.Condition.AND(user.Name, "=", name).AND(user.Pwd, "=", pwd));

            User dbUser = EntityQuery<User>.QueryObject(q);
            return dbUser != null; //查询到用户实体类,表示登录成功
        }

这是OQL早期的条件查询方式,缺点是没法构造复杂的查询条件。

5,操作符重载

OQLCompare 的操作符重载可以简化比较条件,如下所示:

       /// <summary>
        /// 使用用户名密码参数来登录,并使用操作符重载的查询条件比较方式
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public bool Login4(string name, string pwd)
        {
            User user = new User();

            OQL q = OQL.From(user)
                  .Select()
                  .Where( cmp => cmp.Property(user.Name) == name
                               & cmp.Property(user.Pwd)  == pwd  )
               .END;

            User dbUser = EntityQuery<User>.QueryObject(q);
            return dbUser != null; //查询到用户实体类,表示登录成功
        }

6,使用泛型OQL查询(GOQL)

使用泛型OQL查询(GOQL),对于单实体类查询最简单的使用方式,缺点是不能进行“连表查询”,即多个实体类联合查询。

        /// <summary>
        /// 使用用户名密码参数来登录,使用泛型OQL查询(GOQL),对于单实体类查询最简单的使用方式。
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public bool Login5(string name, string pwd)
        {
            User dbUser = OQL.From<User>()
                 .Select()
                 .Where((cmp, user) => cmp.Property(user.Name) == name
                                     & cmp.Property(user.Pwd)  == pwd  )
            .END
            .ToObject();

            return dbUser != null; //查询到用户实体类,表示登录成功
        }

7,使用实体类主键来查询

SOD实体类的“主键”字段是可以修改的,这样你可以随时修改它,就像实体类本来的主键一样,用它来填充数据,本例就是判断是否填充成功当前实体类来判断用户是否可以登录。

       /// <summary>
        /// 使用用户名密码参数来登录,但是根据实体类的主键来填充实体类并判断是否成功。
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public bool Login6(string name, string pwd)
        {
            User user = new User();
            user.PrimaryKeys.Clear();
            user.PrimaryKeys.Add("Name");
            user.PrimaryKeys.Add("Pwd");

            user.Name = name;
            user.Pwd = pwd;
            bool result= EntityQuery<User>.Fill(user);//静态方法,使用默认的连接对象
            return result;
        }

8,查询多条数据

前面的例子都只是查询一条数据,如果需要查询多条数据也很简单,参见下面的例子,如何查询所有姓 zhang 的用户:

        /// <summary>
        /// 模糊查询用户,返回用户列表,使用OQLCompare 委托
        /// </summary>
        /// <param name="likeName">要匹配的用户名</param>
        /// <returns>用户列表</returns>
        public List<User> FuzzyQueryUser(string likeName)
        {
            User user = new User();
            OQL q = OQL.From(user)
              .Select()
              .Where(cmp => cmp.Comparer(user.Name, "like", likeName+"%") )
            .END;

            List<User> users = EntityQuery<User>.QueryList(q);
            return users;
        }

前端调用:

//查询列表
var users=service.FuzzyQueryUser("zhang");
Console.WriteLine("模糊查询姓 张 的用户,数量:{0}",users.Count );

所以,查询多条数据,仅需要使用泛型 EntityQuery对象的QueryList 方法即可。同样,框架也为你提供了OQL对象扩展方法来直接查询列表数据。

9,实体类联合查询

这里不再举例,我的博客文章也多次说明过,请参考下面这个系列文章:

ORM查询语言(OQL)简介--高级篇(续):庐山真貌 深蓝医生 2013-07-30 16:54 阅读:4497 评论:41

ORM查询语言(OQL)简介--高级篇:脱胎换骨 深蓝医生 2013-07-26 17:26 阅读:3274 评论:28

ORM查询语言(OQL)简介--实例篇 深蓝医生 2013-04-01 14:56 阅读:5108 评论:16

ORM查询语言(OQL)简介--概念篇 深蓝医生 2012-10-06 00:58 阅读:4657 评论:25

四、SOD框架的设计原则

SOD框架的整个设计都采用了“条条道路通罗马”的原则,即多模式解决方案,对数据的开发不管是SQL-MAP ,ORM,Data Control 哪种模式都可以“殊途同归”,对于OQL,这个也得到了充分的体现,比如上面的用户登录功能,使用了7 种方式来实现,实际上还有3中查询方式本篇文章没有做成说明;而对于实体类的增,删,改,分别又提供了DbContext,OQL,泛型EntityQuery 等多种方式。

所以,SOD框架的使用非常灵活,你可以根据你的偏好,习惯,环境,来灵活使用,而且也容易扩展,因此,相对于EF这样的ORM框架来,SOD框架的ORM功能没有任何束缚,它自由,灵活,而且轻量,容易扩展,但不妨碍它的强大,比如对于分表分库的查询,数据的批量更新插入修改,数据库锁的直接支持等这些“企业级”数据开发需求的支持。

五、相关资源

本篇文章的源码,已经上传在了框架的开源项目 pwmis.codeplex.com 网站上,可以通过下面的地址查看完整的源码:

http://pwmis.codeplex.com/SourceControl/latest#SOD/Test/SampleORMTest/Program.cs

源码下载,可以在下面的地址查看:

http://pwmis.codeplex.com/releases/view/117822      简单ORM示例程序--新手必读

有关框架更详细而完整的入门指引,请参考下面这篇文章:

PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引

更多完整而详细的信息,请看框架官网地址:

http://www.pwmis.com/sqlmap

框架已经完全开源,参看这篇文章:

一年之计在于春,2015开篇:PDF.NET SOD Ver 5.1完全开源

时间: 2024-10-10 17:18:39

.NET ORM 的 “SOD蜜”--零基础入门篇的相关文章

Linux及Arm-Linux程序开发笔记(零基础入门篇)

Linux及Arm-Linux程序开发笔记(零基础入门篇)  作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/beer/archive/2011/05/05/2037449.html 目录 一.Arm-Linux程序开发平台简要介绍... 3 1.1程序开发所需系统及开发语言... 3 1.2系统平台搭建方式... 4 二.Linux开发平台搭建... 5 2.1安装虚拟工作站... 5 2.2安装Linux虚拟

智能家居——IoT零基础入门篇

概要 本文主要根据笔者从零开始接触硬件,以小白视角开启IoT探索,根据相关资料DIY一个温湿度传感器.后经过探索发现新大陆——Home Assistant&Homebridge,最终实现了一个智能家居设备从数据采集到控制.展示. 整体结构图 智能设备:温湿度传感器 主控芯片:STM32F103C8T http://pic.cnhubei.com/space.php?uid=1913&do=album&id=1108908http://pic.cnhubei.com/space.ph

从零基础入门JavaScript(1)

从零基础入门JavaScript(1) 1.1  Javascript的简史 1995年的时候   由网景公司开发的,当时的名字叫livescript    为了推广自己的livescript,搭了java顺风车,改名为javascript 与此同时,     微软因此在自身的浏览器里,也推出了自己的脚本语言 jscript 1997年时候,  由ECMA(欧洲计算机制造商协会)出面,推出了一套javascript的规范,Ecmascript ,规范提出js由三部分组成 JS的组成: ECMAS

鱼C《零基础入门学习Python》10-17节课时知识点总结

第10讲:列表:一个打了激素的数组 1. 列表都可以存放一些什么东西?  我们说 Python 的列表是一个打了激素的数组,如果把数组比喻成集装箱,那么 Python 的列表就是一个大仓库,Ta 可以存放我们已经学习过的任何数据类型. 2. 向列表增加元素有哪些方法?  三种方法想列表增加元素,分别是:append().extend() 和 insert().    3. append() 方法和 extend() 方法都是向列表的末尾增加元素,请问他们有什么区别?  append() 方法是将

.NET零基础入门05:委托与事件

一:前言 本小节,我们需要停一停我们的小游戏开发,虽然它现在还不完美,还很简单,甚至还有BUG.但是,为了更好的理解C#,现在到了该深入了解一些基础知识的时候了. 当然,实际上,本小节内容对于零基础入门的初学者来说,还是有点难了.委托与事件,如果只是泛泛的说一下,可能就是一两句话.但是,我们的课程要遵循一个原则:知其然,知其所以然.所以,本小节的内容实际上有点多,但是我希望大家细细品味,争取彻底消化委托和事件这两个概念. 同时,本课程还要教会大家使用一个工具,分析代码. 二:委托的现实场景:卖家

零基础入门jQuery视频教程

零基础入门jQuery最新版开发.NET富客户端应用(选择器.DOM操作.事件和动画.Ajax应用.插件.Mobile)课程分类:.NET+Jquery适合人群:初级课时数量:35课时用到技术:javascript,ajax,jquery,handler涉及项目:各知识点的项目案例和名为JaneShop的品牌服装和包包的购物网站咨询qq:1840215592 零基础入门jQuery视频教程详细查看:http://www.ibeifeng.com/goods-425.html 零基础入门jQuer

干货分享:MySQL零基础入门视频教程!

首先给大家介绍一下数据库工程师,数据库工程师(Database Engineer),是从事管理和维护数据库管理系统(DBMS) 的相关工作人员的统称,他属于运维工程师的一个分支,主要负责业务数据库从设计.测试到部署交付的全生命周期管理.数据库工程师的核心目标是保证数据库管理系统的稳定性.安全性.完整性和高性能. 今天在这里给大家分享一个干货教程,MySQL零基础入门视频教程,希望能帮助到大家! 课程目录: 一. MySQL课程介绍和MySQL的基础概念(1)二. MySQL基础概念之存储引擎(2

Cloudera Manager、CDH零基础入门、线路指导 http://www.aboutyun.com/thread-9219-1-1.html (出处: about云开发)

Cloudera Manager.CDH零基础入门.线路指导http://www.aboutyun.com/thread-9219-1-1.html(出处: about云开发) 问题导读:1.什么是cloudera CM .CDH?2.CDH.CM有哪些版本?3.CDH.CM有哪些安装方式?4.CDH如何开发? <ignore_js_op> 我们知道cloudera CDH 是为简化hadoop的安装,也对对hadoop做了一些封装.那么我们就像尝试学习cloudera.cloudera本质h

.NET零基础入门09:SQL必知必会

一:前言 仿佛到了更进一步的时候了,每一个程序员迟早都会遇到数据存储的问题.我们拿什么来存储程序产生的数据?举例来说,用什么来存储我们的打老鼠游戏每次的成绩呢?选择如下: 1:内存中.缺点,退出游戏,数据就没了: 2:文件中.好办法!缺点,自己解析文本,把文本变成我们程序中的数据,这个解析的过程叫做协议.协议这个词听上去够恐怖吧,实际上说白了无非就是数据格式怎么样,API接口怎么样之类的东东. 3:数据库.好办法!好吧,数据库文件其实也就是硬盘上的文件,只不过数据库本身就已经为我们定义好了数据格