EF 批量更新删除(linq篇)
刚开始用EF很多东西都不会用,事后想想都很简单的东西总是用很麻烦的方式实现
1: EF的联合查询 inner join
很久很久以前我是这么写一个列表展示的,其中有两个字段Contractor和Maintaniner是需要inner join 链接查询,
但是当时太年轻不会用ef的链接,所以用了最笨的方法,代码如下
[Permission("L_Business")]
public ActionResult Index(BusinessRequest request)
{
//合作商户列表展示
var result = this.MMService.GetBusinessList(request);
result = this.GetContractorName(result);
result = this.GetMaintainerName(result);
return View(result);
}
/// <summary>
/// 获取创建者姓名
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
private IEnumerable<Business> GetContractorName(IEnumerable<Business> result)
{
foreach (var item in result)
{
var staff = this.OAService.GetStaff(item.ContractorID);
if (staff != null) item.ConractorName = staff.Name;
}
return result;
}
/// <summary>
/// 获取创建者姓名
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
private IEnumerable<Business> GetMaintainerName(IEnumerable<Business> result)
{
foreach (var item in result)
{
var staff = this.OAService.GetStaff(item.MaintainerID);
if (staff != null) item.MaintainerName = staff.Name;
}
return result;
}
代码很傻,需要循环多次去查出来每行中的Contractor和Maintaniner,这样是很影响效率,同时显得技术比较low的,下面的方式就好多了
首先:在model中设置链接外键
public class Business : ModelBase
{
//签约人ID
public int ContractorID { get; set; }
//外键指明要连接的表
[ForeignKey("ContractorID")]
public Staff Contractor { get; set; } //签约日期
public DateTime ContractDate { get; set; }
//维护人员ID
public int MaintainerID { get; set; }
[ForeignKey("MaintainerID")]
public Staff Maintainer { get; set; }
}
然后:在数据层中查询时使用Include查询
public IEnumerable<Business> GetBusinessList(BusinessRequest request = null)
{
request = request ?? new BusinessRequest();
using (var dbContext = new MMDbContext())
{
//include可以实现在model中设置的外检链接
IQueryable<Business> business = dbContext.Business.Include("Contractor").Include("Maintainer");
business = business.Where(b => b.IsDelete == );
if (!string.IsNullOrEmpty(request.Name))
{
business = business.Where(b => b.Name.Contains(request.Name));
}
return business.OrderByDescending(b => b.ID).ToPagedList(request.PageIndex, request.PageSize);
} }
最后:在页面展示的时候
[Permission("L_Business")]
public ActionResult Index(BusinessRequest request)
{
//合作商户列表展示
var result = this.MMService.GetBusinessList(request);
return View(result);
}
<td>
@(m.Contractor!=null?m.Contractor.Name:"")
</td> <td>
@(m.Maintainer!=null?m.Maintainer.Name:"")
</td>
但是用include 的时候用 SQL Server Profiler查看语句会发现第一个include和第二个不一样
SELECT TOP () *
FROM ( SELECT [Extent1].[ID] AS [ID1], [Extent1].[Name] AS [Name1], [Extent1].[Address] AS [Address], [Extent1].[Contact] AS [Contact], [Extent1].[Mobile] AS [Mobile1], [Extent1].[BankID] AS [BankID], [Extent1].[BankAccount] AS [BankAccount], [Extent1].[AccountName] AS [AccountName], [Extent1].[AccountNumber] AS [AccountNumber], [Extent1].[ContractorID] AS [ContractorID], [Extent1].[ContractDate] AS [ContractDate], [Extent1].[MaintainerID] AS [MaintainerID], [Extent1].[Remark] AS [Remark1], [Extent1].[Status] AS [Status], [Extent1].[IsDelete] AS [IsDelete], [Extent1].[PayStatus] AS [PayStatus], [Extent1].[Balance] AS [Balance], [Extent1].[CreateDate] AS [CreateDate1], [Extent1].[CreateStaffID] AS [CreateStaffID1], [Extent1].[CreateStaffName] AS [CreateStaffName1], [Extent2].[ID] AS [ID2], [Extent2].[Number] AS [Number1], [Extent2].[Name] AS [Name2], [Extent2].[Mobile] AS [Mobile2], [Extent2].[MobileTwo] AS [MobileTwo1], [Extent2].[Gender] AS [Gender1], [Extent2].[Phone] AS [Phone1], [Extent2].[Remark] AS [Remark2], [Extent2].[Email] AS [Email1], [Extent2].[City] AS [City1], [Extent2].[Province] AS [Province1], [Extent2].[DeleteMark] AS [DeleteMark1], [Extent2].[IsActive] AS [IsActive1], [Extent2].[IsCreateAccount] AS [IsCreateAccount1], [Extent2].[ComeInDate] AS [ComeInDate1], [Extent2].[DepartureDate] AS [DepartureDate1], [Extent2].[CompanyID] AS [CompanyID1], [Extent2].[CreateDate] AS [CreateDate2], [Extent2].[CreateStaffID] AS [CreateStaffID2], [Extent2].[CreateStaffName] AS [CreateStaffName2], [Extent3].[ID] AS [ID3], [Extent3].[Number] AS [Number2], [Extent3].[Name] AS [Name3], [Extent3].[Mobile] AS [Mobile3], [Extent3].[MobileTwo] AS [MobileTwo2], [Extent3].[Gender] AS [Gender2], [Extent3].[Phone] AS [Phone2], [Extent3].[Remark] AS [Remark3], [Extent3].[Email] AS [Email2], [Extent3].[City] AS [City2], [Extent3].[Province] AS [Province2], [Extent3].[DeleteMark] AS [DeleteMark2], [Extent3].[IsActive] AS [IsActive2], [Extent3].[IsCreateAccount] AS [IsCreateAccount2], [Extent3].[ComeInDate] AS [ComeInDate2], [Extent3].[DepartureDate] AS [DepartureDate2], [Extent3].[CompanyID] AS [CompanyID2], [Extent3].[CreateDate] AS [CreateDate3], [Extent3].[CreateStaffID] AS [CreateStaffID3], [Extent3].[CreateStaffName] AS [CreateStaffName3], row_number() OVER (ORDER BY [Extent1].[ID] DESC) AS [row_number]
FROM [dbo].[MM_Business] AS [Extent1]
INNER JOIN [dbo].[OA_Staff] AS [Extent2] ON [Extent1].[ContractorID] = [Extent2].[ID]
LEFT OUTER JOIN [dbo].[OA_Staff] AS [Extent3] ON [Extent1].[MaintainerID] = [Extent3].[ID]
WHERE = [Extent1].[IsDelete]
) AS [Filter1]
WHERE [Filter1].[row_number] >
ORDER BY [Filter1].[ID1] DESC
使用 SQL Server Profiler 检测的native sql 显示 第一次的include 为 inner join 第二个为left outer join,这里是一个知识盲点,以后还要在做研究
2:EF 多次更新和删除
图样图森破,直接上代码
public void SaveBillAndOrder(Bill model, List<Order> orderList)
{
using (var dbContext = new WebSiteDbContext())
{
model = dbContext.Insert(model);
//添加Order
if (orderList.Count > )
{
//增加订单,使用循环方式添加一个
foreach (var item in orderList)
{
var entity = dbContext.Insert(item);
}
}
dbContext.SaveChanges();
}
}
这里展示一个code,是我在一个多次插入的例子,还有很多是批量删除,批量更新都是用了foreach的方式
后来想,ef这么强大的工具不能就这样吧,所以开始 百度
没有包的同学可以直接nuget https://github.com/loresoft/EntityFramework.Extended
我的程序中用的是 EntityFramework.Extensions 自带的,就没有下载了
public void CancelRechargeCardPrepaymentByBillID(int BillID)
{
using (var dbContext = new WebSiteDbContext())
{
dbContext.RechargeCardPrepayments.Where(r => r.BillID == BillID).Update(r => new RechargeCardPrepayment { IsValid = (int)EnumRechargePrepaymentIsValid.WX });
dbContext.SaveChanges();
}
}
实验发现效率还是可以没有出现每一条写一个insert或者update 的情况(ps:删除的话直接把Update换成Delete()就可以了)
Native sql 如下
exec sp_executesql N'UPDATE [dbo].[CRM_CardAndBalancePrepayment] SET
[IsValid] = @p__update__0
FROM [dbo].[CRM_CardAndBalancePrepayment] AS j0 INNER JOIN (
SELECT
[Extent1].[ID] AS [ID]
FROM [dbo].[CRM_CardAndBalancePrepayment] AS [Extent1]
WHERE [Extent1].[BillID] = @p__linq__0
) AS j1 ON (j0.[ID] = j1.[ID])',N'@p__linq__0 int,@p__update__0 int',@p__linq__0=143817,@p__update__0=1
写到这里脑海中突然想起了首歌:
- 其实很简单 其实很自然
- 两个人的爱由两人分担
- 其实并不难 是你太悲观
- 隔着一道墙不跟谁分享
分享出来,哈哈哈哈,
EF 批量更新删除(linq篇)的更多相关文章
- Devexpress + wcf +ef 批量更新处理
项目结构: 1.客户端:Winform, 2.数据访问:EF4.0(从数据库生成模型-懒人必需这样) 3.DTO:直接使用EF实体 4.服务端:WCF 托管在IIS中采用basicHttp帮定(这样可 ...
- EF 批量 循环删除
var list = db.T_xAppRecord.Where(u => u.Id == 1).ToList(); //2.0 遍历集合,将 要删除的 对象 的代理对象的State 设置为 D ...
- Django REST Framework批量更新rest_framework_extensions
Django REST framework 是一套基于Django框架编写RESTful风格API的组件. 其中mixins配合viewsets能极其方便简化对数据的增删改查, 但本身并没有对数据的批 ...
- LINQ To SQL在N层应用程序中的CUD操作、批量删除、批量更新
原文:LINQ To SQL在N层应用程序中的CUD操作.批量删除.批量更新 0. 说明 Linq to Sql,以下简称L2S. 以下文中所指的两层和三层结构,分别如下图所示: 准确的说,这里 ...
- EF结合SqlBulkCopy实现高效的批量数据插入 |EF插件EntityFramework.Extended实现批量更新和删除
原文链接:http://blog.csdn.net/fanbin168/article/details/51485969 批量插入 (17597条数据批量插入耗时1.7秒) using Sys ...
- 【转】Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)
E文好的可以直接看https://github.com/loresoft/EntityFramework.Extended 也可以在nuget上直接安装这个包,它的说明有点过时了,最新版本已经改用对I ...
- (转)Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)
转自:http://www.cnblogs.com/jinzhao/archive/2013/05/31/3108755.html 今天乍一看,园子里居然没有关于这个类库的文章,实在是意外毕竟已经有很 ...
- ado.net 批量添加 更新 删除
自曾列就别往下看 别折腾了 使用 SqlBulkCopy ,dataTable 必须跟sql里面的表字段完全一样 下面在sqlserver中演示 mysql 请google MySqlBulkLo ...
- Hibernate批量更新和批量删除批量添加(转)
通常,在一个Session对象的缓存中只存放数量有限的持久化对象,等到Session对象处理事务完毕,还要关闭Session对象,从而及时释放Session的缓存占用的内存.批量处理数据是指在一个事务 ...
随机推荐
- 云计算之路-阿里云上:禁用Windows虚拟内存引发的重启
昨天(2013年8月6日)下午,承载www.cnblogs.com主站的两台云服务器分别自动重启了1次,由于这两台云服务器使用了负载均衡(SLB),重启并未影响网站的正常访问. 与这次重启相关的Win ...
- ThreadLocal的简单使用(读书笔记)
从ThreadLocal的名字上可以看到,这是一个线程局部变量,也就是说,只有当前线程可以访问,既然是只有当前线程可以访问的数据,自然是线程安全的. public class ThreadL ...
- 04-常见内存错误以及valgrind使用
04-常见内存错误以及valgrind使用 代码段: 仅仅读数据,因此对这一部分的数据.试图写仅仅读数据,这个在编译的时候基本上能够检測. 数据段/BSS段: 未初始化直接訪问,即使没有显示初始化,仍 ...
- Python Socket API 笔记
将上节中的C#该成Python版的容易程度大大超出了我的意料之外.从来没有发现,仅仅用灰尘简单的几句话就实现了该程序的主要功能,可见python的简易和强大之处.这里先对SocketAPI 做一下总结 ...
- Unity3D教程宝典之Web服务器篇:(第一讲)服务器的架设
转载自风宇冲Unity3D教程学院 引言:本文主要介绍WAMP服务器的架设. 第一部分WAMP介绍;第二部分WAMP安装及使用. 第一部分WAMP介绍 什 ...
- 神秘值分解(Singular Value Decomposition)
- 线性变化的几何表现 首先看下简单的矩阵,这是一个对角矩阵 M=(3001) 我们先用这个对角矩阵乘以一个点来看看它的几何变化. (3001)∗(xy)=(3xy) 在几何上就相当于把原来的向量x轴 ...
- 改变Fragment的默认动画
FragmentTransaction ft = getFragmentManager().beginTransaction(); //设置进入退出动画 ft.setCustomAnimations( ...
- node.js零基础详细教程(1):安装+基础概念
第一章 建议学习时间2小时 课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...
- csv导出文件中有html
最近遇到再导出csv文件时,csv文件中包含html代码 一开始以为导出的数据量太大,减少数据后仍然出现html代码,此时想到应该与数据有关,仔细观察csv中的数据,有的单元里面是空值, 对比原始数据 ...
- DNS的概念,用途,DNS查询的实现算法
1.DNS的概念,用途 DNS是由解析器以及域名服务器组成的. 域名服务器是指保存有该网络中所有主机的域名和对应IP地址,并具有将域名转换为IP地址功能的服务器. DNS ...