本篇主要对常规数据操作的处理和实体框架的处理代码进行对比,以便更容易学习理解实体框架里面,对各种数据库处理技巧,本篇介绍几种数据库操作的代码,包括写入中间表操作、联合中间表获取对象集合、递归操作、设置单一字段的修改等几种方式。

1、写入中间表操作

一般情况下,我们可以通过执行数据库脚本方式写入。

        /// <summary>
/// 增加用户IP信息
/// </summary>
/// <param name="userID"></param>
/// <param name="blackID"></param>
public void AddUser(int userID, string blackID)
{
string commandText = string.Format("INSERT INTO T_ACL_BLACKIP_USER(User_ID, BLACKIP_ID) VALUES({0}, '{1}')", userID, blackID);
base.SqlExecute(commandText);
} /// <summary>
/// 移除用户IP 信息
/// </summary>
/// <param name="userID"></param>
/// <param name="blackID"></param>
public void RemoveUser(int userID, string blackID)
{
string commandText = string.Format("DELETE FROM T_ACL_BLACKIP_USER WHERE User_ID={0} AND BLACKIP_ID='{1}'", userID, blackID);
base.SqlExecute(commandText);
}
        /// <summary>
/// 执行一些特殊的语句
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="parameters">要应用于命令字符串的参数</param>
public virtual int SqlExecute(string sql, params object[] parameters)
{
return baseContext.Database.ExecuteSqlCommand(sql, parameters);
}

上面间接用来执行脚本方式写入中间表数据;但是,如果我们采用Entity Framework的方式来处理,也是可以的,例如我们为角色添加和移除用户的代码如下所示。

        public void AddUser(int userID, int roleID)
{
var role = new Role() { ID = roleID, Functions = new List<Function>() };
context.Roles.Attach(role); User user = new User() { ID = userID };
context.Users.Attach(user); int count = this.GetQueryable().Where(s => s.ID == roleID).Count(s => s.Users.Any(p => p.ID == userID));
if (count == )
{
role.Users.Add(user);
} context.SaveChanges();
} public void RemoveUser(int userID, int roleID)
{
var role = this.GetQueryable().FirstOrDefault(s => s.ID == roleID);
var deleted = role.Users.FirstOrDefault(s => s.ID == userID);
if (deleted != null)
{
role.Users.Remove(deleted);
} context.SaveChanges();
}

如果我们需要重新写入中间列表的数据,那么处理方式如下所示。

        public bool EditOuUsers(int ouID, List<int> newUserList)
{
//先清空
Ou ou = this.GetQueryable().FirstOrDefault(s => s.ID == ouID);
ou.Users.Clear();
context.SaveChanges(); //设置新的列表
var users = context.Users.Where(s => newUserList.Contains(s.ID)).ToList();
ou.Users = users; return context.SaveChanges() > ;
}

2、联合中间表获取对象集合

一般情况下,我们在数据访问层需要结合中间表进行查询的时候,常用的处理方式是在SQL语句里面联合两个表进行处理。如联合机构角色中间表、机构用户中间表来获取对应机构的列表操作如下所示。

        public List<OUInfo> GetOUsByRole(int roleID)
{
string sql = "SELECT * FROM T_ACL_OU INNER JOIN T_ACL_OU_Role On [T_ACL_OU].ID=T_ACL_OU_Role.OU_ID WHERE Role_ID = " + roleID;
return this.GetList(sql, null);
} public List<OUInfo> GetOUsByUser(int userID)
{
string sql = "SELECT * FROM T_ACL_OU INNER JOIN T_ACL_OU_User On [T_ACL_OU].ID=T_ACL_OU_User.OU_ID WHERE User_ID = " + userID;
return this.GetList(sql, null);
}

如果是在实体框架里面,我们不能那么直接操作SQL语句,尽可能用内置的LINQ查询操作,使用的时候,你也发现很简单的。

        public IList<Ou> GetOUsByRole(int roleID)
{
return this.GetQueryable().Where(s => s.Roles.Any(c => c.ID == roleID)).ToList();
} public IList<Ou> GetOUsByUser(int userID)
{
return this.GetQueryable().Where(s => s.Users.Any(c => c.ID == userID)).ToList();
}

3、递归操作

很多时候,我们表的数据是有层次结构的,有时候,需要根据父ID获取下面的子集列表的时候,我们就需要用到递归。常规的SQL处理方式,可以如下实现。

       /// <summary>
/// 根据指定机构节点ID,获取其下面所有机构列表
/// </summary>
/// <param name="parentId">指定机构节点ID</param>
/// <returns></returns>
public List<OUInfo> GetAllOUsByParent(int parentId)
{
List<OUInfo> list = new List<OUInfo>();
string sql = string.Format("Select * From {0} Where Deleted <> 1 Order By PID, Name ", tableName); DataTable dt = SqlTable(sql);
string sort = string.Format("{0} {1}", GetSafeFileName(sortField), isDescending ? "DESC" : "ASC");
DataRow[] dataRows = dt.Select(string.Format(" PID = {0}", parentId), sort);
for (int i = ; i < dataRows.Length; i++)
{
string id = dataRows[i]["ID"].ToString();
list.AddRange(GetOU(id, dt));
} return list;
} private List<OUInfo> GetOU(string id, DataTable dt)
{
List<OUInfo> list = new List<OUInfo>(); OUInfo ouInfo = this.FindByID(id);
list.Add(ouInfo); string sort = string.Format("{0} {1}", GetSafeFileName(sortField), isDescending ? "DESC" : "ASC");
DataRow[] dChildRows = dt.Select(string.Format(" PID={0} ", id), sort);
for (int i = ; i < dChildRows.Length; i++)
{
string childId = dChildRows[i]["ID"].ToString();
List<OUInfo> childList = GetOU(childId, dt);
list.AddRange(childList);
}
return list;
}

如果这样的实现,在实体框架实现,那么应该如何处理呢?

        public IList<Ou> GetAllOUsByParent(int parentId)
{
List<Ou> list = this.GetQueryable().Where(s => s.PID == parentId).Where(s => !s.IsDeleted).OrderBy(s => s.PID).OrderBy(s => s.Name).ToList();
foreach(Ou info in list)
{
list.AddRange(GetAllOUsByParent(info.ID));
}
return list;
}

是不是觉得简单很多了呢?

4、设置单一字段的修改

有时候,我们可能需要更新列表里面的某些字段,那么如果采用SQL操作处理,那么代码如下所示。

        /// <summary>
/// 设置删除标志
/// </summary>
/// <param name="id">记录ID</param>
/// <param name="deleted">是否删除</param>
/// <param name="trans">事务对象</param>
/// <returns></returns>
public bool SetDeletedFlag(object id, bool deleted = true, DbTransaction trans = null)
{
int intDeleted = deleted ? : ;
string sql = string.Format("Update {0} Set Deleted={1} Where ID = {2} ", tableName, intDeleted, id);
return SqlExecute(sql, trans) > ;
}

如果是采用实体框架,那么处理代码如下所示。

        public bool SetDeletedFlag(object id, bool deleted = true)
{
var ou = new Ou() { ID = id.ToString().ToInt32(), IsDeleted = deleted };
context.Ous.Attach(ou); context.Entry(ou).Property(x => x.Deleted).IsModified = true;
return context.SaveChanges() > ;
}

如果更新多个字段,那么常规的SQL方式代码如下所示。

        /// <summary>
/// 更新用户登录的时间和IP地址
/// </summary>
/// <param name="id">用户ID</param>
/// <param name="ip">IP地址</param>
/// <param name="macAddr">MAC地址</param>
/// <returns></returns>
public bool UpdateUserLoginData(int id, string ip, string macAddr)
{
//先复制最后的登录时间和IP地址
string sql = string.Format("Update {0} set LastLoginIP=CurrentLoginIP,LastLoginTime=CurrentLoginTime,LastMacAddress=CurrentMacAddress Where ID={1}", tableName, id);
Database db = CreateDatabase();
DbCommand dbCommand = db.GetSqlStringCommand(sql);
db.ExecuteNonQuery(dbCommand); sql = string.Format("Update {0} Set CurrentLoginIP='{1}',CurrentMacAddress='{2}', CurrentLoginTime=@CurrentLoginTime Where ID = {3}", tableName, ip, macAddr, id);
dbCommand = db.GetSqlStringCommand(sql);
db.AddInParameter(dbCommand, "CurrentLoginTime", DbType.DateTime, DateTime.Now);
return db.ExecuteNonQuery(dbCommand) > ;
}

多个字段的更新,使用实体框架则是如下所示。

        public bool UpdateUserLoginData(int id, string ip, string macAddr)
{
//先复制最后的登录时间和IP地址
string tableName = context.GetTableName<User>();
string sql = string.Format("Update {0} set LastLoginIP=CurrentLoginIP,LastLoginTime=CurrentLoginTime,LastMacAddress=CurrentMacAddress Where ID={1}", tableName, id);
SqlExecute(sql); var obj = new User() { ID = id.ToString().ToInt32(), CurrentLoginIP = ip, CurrentMacAddress = macAddr, CurrentLoginTime = DateTime.Now };
context.Users.Attach(obj);
context.Entry(obj).Property(x => x.CurrentLoginIP).IsModified = true;
context.Entry(obj).Property(x => x.CurrentMacAddress).IsModified = true;
context.Entry(obj).Property(x => x.CurrentLoginTime).IsModified = true;
return context.SaveChanges() > ;

这个系列文章如下所示:

Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)

Entity Framework 实体框架的形成之旅--利用Unity对象依赖注入优化实体框架(2)

Entity Framework 实体框架的形成之旅--基类接口的统一和异步操作的实现(3)

Entity Framework 实体框架的形成之旅--实体数据模型 (EDM)的处理(4)

Entity Framework 实体框架的形成之旅--Code First的框架设计(5)

Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)

Entity Framework 实体框架的形成之旅--数据传输模型DTO和实体模型Entity的分离与联合

Entity Framework 实体框架的形成之旅--界面操作的几个典型的处理(8)

Entity Framework 实体框架的形成之旅--几种数据库操作的代码介绍(9)

Entity Framework 实体框架的形成之旅--几种数据库操作的代码介绍(9)的更多相关文章

  1. Entity Framework 实体框架的形成之旅--实体数据模型 (EDM)的处理(4)

    在前面几篇关于Entity Framework 实体框架的介绍里面,已经逐步对整个框架进行了一步步的演化,以期达到统一.高效.可重用性等目的,本文继续探讨基于泛型的仓储模式实体框架方面的改进优化,使我 ...

  2. Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

    在前阵子,我对实体框架进行了一定的研究,然后把整个学习的过程开了一个系列,以逐步深入的方式解读实体框架的相关技术,期间每每碰到一些新的问题需要潜入研究.本文继续前面的主题介绍,着重从整体性的来总结一下 ...

  3. Entity Framework 实体框架的形成之旅--为基础类库接口增加单元测试,对基类接口进行正确性校验(10)

    本篇介绍Entity Framework 实体框架的文章已经到了第十篇了,对实体框架的各个分层以及基类的封装管理,已经臻于完善,为了方便对基类接口的正确性校验,以及方便对以后完善或扩展接口进行回归测试 ...

  4. Entity Framework 实体框架的形成之旅--界面操作的几个典型的处理(8)

    在上篇随笔<Entity Framework 实体框架的形成之旅--数据传输模型DTO和实体模型Entity的分离与联合>里面,介绍了在Entity Framework 实体框架里面引入了 ...

  5. Entity Framework 实体框架的形成之旅--数据传输模型DTO和实体模型Entity的分离与联合

    在使用Entity Framework 实体框架的时候,我们大多数时候操作的都是实体模型Entity,这个和数据库操作上下文结合,可以利用LINQ等各种方便手段,实现起来非常方便,一切看起来很美好.但 ...

  6. Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)

    在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...

  7. Entity Framework 实体框架的形成之旅--Code First的框架设计(5)

    在前面几篇介绍了Entity Framework 实体框架的形成过程,整体框架主要是基于Database First的方式构建,也就是利用EDMX文件的映射关系,构建表与表之间的关系,这种模式弹性好, ...

  8. Entity Framework 实体框架的形成之旅--基类接口的统一和异步操作的实现(3)

    在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...

  9. Entity Framework 实体框架的形成之旅--利用Unity对象依赖注入优化实体框架(2)

    在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...

随机推荐

  1. DDD领域驱动设计之聚合、实体、值对象

    关于具体需求,请看前面的博文:DDD领域驱动设计实践篇之如何提取模型,下面是具体的实体.聚合.值对象的代码,不想多说什么是实体.聚合等概念,相信理论的东西大家已经知晓了.本人对DDD表示好奇,没有在真 ...

  2. [nRF51822] 1、一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO

    最近用nRF51822写了个天马4线SPI的1.77寸LCD彩屏驱动,效果如下: 屏幕的规格资料为:http://pan.baidu.com/s/1gdfkr5L 屏幕的驱动资料为:http://pa ...

  3. AngularJS快速入门指南15:API

    thead>tr>th, table.reference>tbody>tr>th, table.reference>tfoot>tr>th, table ...

  4. iOS xcode6 添加.pch文件

    1, 新建文件 (command+N)选择other组,再次选择pch,输入文件名保存. eg: 创建的工程为Demo; 创建文件名为DemoPrefixHeader.pch 2,到工程里面的buil ...

  5. MVVM架构~knockoutjs系列之验证信息自定义输出~续

    返回目录 上一讲中,我以一个实际中的例子说明了knockoutjs的自定义验证功能,在使用过程中,出现了一个问题,当然了不是问题,只是一种需求,上一讲中自定义验证的表现是:当页面加载后,自动显示有问题 ...

  6. [全文检索]Lucene基础入门.

    本打算直接来学习Solr, 现在先把Lucene的只是捋一遍. 本文内容: 1. 搜索引擎的发展史 2. Lucene入门 3. Lucene的API详解 4. 索引调优 5. Lucene搜索结果排 ...

  7. 关于python的最大递归层数详解

    在阅读http://www.cnblogs.com/skabyy/p/3451780.html这篇文章的时候,实验yield的流式迭代素数的时候发现有个问题,故详细记录下来. 首先来看看python默 ...

  8. Atitit vod ver 12 new feature v12 pb2 影吧 视频 电影 点播 播放系统v12新特性

    Atitit vod ver 12 new feature v12 pb2 影吧 视频 电影 点播 播放系统v12新特性 项目分离从独立的se ver Run mode from brow ex to ...

  9. Atitit.编译原理与概论

    Atitit.编译原理与概论 编译原理 词法分析 Ast构建,语法分析 语意分析 6 数据结构  1. ▪ 记号 2. ▪ 语法树 3. ▪ 符号表 4. ▪ 常数表 5. ▪ 中间代码 1. ▪ 临 ...

  10. VisualSVN-Server 安装以及使用教程

    VisualSVN Server是免费的(代码管理工具),VisualSvn Server是SVN的服务器端 官网下载地址 安装VisualSVN-Server示例: 下载完安装包后,以安装Visua ...