EF中的批量操作

摘要:
阅读目录插入更新删除在使用EF的过程中,我们经常会遇到需要批量操作数据的场景,批量操作有的时候不仅能提高性能,比如使用SqlBulkCopy进入批量插入的时候,而且比较方便操作,提高效率。那么这篇文章就来总结EF中的那些批量操作。=ConnectionState.Closed){db.Database.Connection.Close();}}当然SqlBulkCopy的操作封装在了DBHelper中了,后面会附上DBHelper.BulkInsert的实现。using{//单个删除varentity=db.ProdImageSet.FirstOrDefault;db.ProdImageSet.Remove;db.SaveChanges();}2,批量删除示例代码如下。using{//批量删除varentitys=db.ProdImageSet.Where;entitys.ToList().ForEach;//不加这句也可以,为什么?

阅读目录

在使用EF的过程中,我们经常会遇到需要批量操作数据的场景,批量操作有的时候不仅能提高性能,比如使用SqlBulkCopy进入批量插入的时候,而且比较方便操作,提高效率。那么这篇文章就来总结EF中的那些批量操作。

回到顶部

插入

1,单个插入

单个插入很简单,只需要构造好实体,然后调用DbSet的Add方法,最后SaveChanges就行,示例代码如下。

复制代码
using (var db = new PackageFHContext()) 
{ 
    // 单个插入 
    var entity = new ProdImage 
    { 
    ProductID = 1807, 
    Type = 7, 
    Priority = 0, 
    Url = " http://www.baidu.com/abc.png", 
    Alt = "test", 
    Creator = "system", 
    CreateOn = DateTime.Now 
    }; 
    db.ProdImageSet.Add(entity); 
    db.SaveChanges(); 
}
复制代码

2,批量插入

很多时候我们需要向同一数据表插入大量的数据,如果插入一条就调一次SaveChanges这样性能很低,需要频繁地访问数据库。为了解决这个问题,可以使用SqlBulkCopy来批量插入数据,这样很大地提高性能。示例代码如下。

复制代码
using (var db = new PackageFHContext()) 
{ 
    // 批量插入(使用到SqlBulkCopy) 
    var prodImages = new List<ProdImage>(); 
    for (int i = 0; i < 50; i++) 
    { 
        prodImages.Add(new ProdImage 
        { 
        ProductID = 1807, 
        Type = 7, 
        Priority = 0, 
        Url = " http://www.baidu.com/abc.png", 
        Alt = "test" + i, 
        Creator = "system", 
        CreateOn = DateTime.Now 
        }); 
    } 

    if (db.Database.Connection.State != ConnectionState.Open) 
    { 
        db.Database.Connection.Open(); 
    } 

    PackageFH.Common.DBHelper.BulkInsert((SqlConnection)db.Database.Connection, "dbo.Pkg_ProdImage", prodImages); 

    if (db.Database.Connection.State != ConnectionState.Closed) 
    { 
        db.Database.Connection.Close(); 
    } 
}
复制代码

当然SqlBulkCopy的操作封装在了DBHelper中了,后面会附上DBHelper.BulkInsert的实现。

回到顶部

更新

1,单个更新

单个更新很简单,只需要先查询出那条数据,然后修改字段的值,最后SaveChanges就行。示例代码如下。

复制代码
using (var db = new PackageFHContext())
{
    // 单个更新
    var entity = db.ProdImageSet.FirstOrDefault(p => p.ImageID == 275695);
    entity.Alt = "ooooooooooo";
    db.SaveChanges();
}
复制代码

2,批量更新

我们可以先查找要更新的那些记录,然后遍历修改字段的值,最后调用SaveChanges提交更新。示例代码如下。

复制代码
using (var db = new PackageFHContext())
{
    // 批量更新
    var entitys = db.ProdImageSet.Where(p => p.ProductID == 1807 && p.Type == 7);
    var j = 1;
    entitys.ToList().ForEach(item =>
    {
        item.Alt = "update test" + j;
        db.Entry(item).State = System.Data.Entity.EntityState.Modified; //不加这句也可以,为什么?
        j++;
    });
    db.SaveChanges();
}
复制代码

通过SQL Profiler监控可以看到,最后生成的还是很多的UPDATE语句,也就是说每更新一条就是一个UPDATE语句。

回到顶部

删除

1,单个删除

示例代码如下。

复制代码
using (var db = new PackageFHContext())
{
    // 单个删除
    var entity = db.ProdImageSet.FirstOrDefault(p => p.ImageID == 275695);
    db.ProdImageSet.Remove(entity);
    db.SaveChanges();
}
复制代码

2,批量删除

示例代码如下。

复制代码
using (var db = new PackageFHContext())
{
    // 批量删除
    var entitys = db.ProdImageSet.Where(p => p.ProductID == 1783 && p.Type == 0);
    entitys.ToList().ForEach(entity => db.Entry(entity).State = System.Data.Entity.EntityState.Deleted); //不加这句也可以,为什么?
    db.ProdImageSet.RemoveRange(entitys);
    db.SaveChanges();
}
复制代码

通过SQL Profiler监控,结果生成的也是多条DELETE语句。

附:DBHelper.BulkInsert的实现代码

复制代码
 1 public static void BulkInsert<T>(SqlConnection conn, string tableName, IList<T> list)
 2 {
 3     using (var bulkCopy = new SqlBulkCopy(conn))
 4     {
 5         bulkCopy.BatchSize = list.Count;
 6         bulkCopy.DestinationTableName = tableName;
 7 
 8         var table = new DataTable();
 9         var props = TypeDescriptor.GetProperties(typeof(T), new Attribute[] { new DatabaseTableColumnAttribute() })
10             //Dirty hack to make sure we only have system data types 
11             //i.e. filter out the relationships/collections
12             .Cast<PropertyDescriptor>()
13             .Where(propertyInfo => propertyInfo.PropertyType.Namespace.Equals("System"))
14             .ToArray();
15 
16         foreach (var propertyInfo in props)
17         {
18             bulkCopy.ColumnMappings.Add(propertyInfo.Name, propertyInfo.Name);
19             table.Columns.Add(propertyInfo.Name, Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType);
20         }
21 
22         var values = new object[props.Length];
23         foreach (var item in list)
24         {
25             for (var i = 0; i < values.Length; i++)
26             {
27                 values[i] = props[i].GetValue(item);
28             }
29 
30             table.Rows.Add(values);
31         }
32 
33         bulkCopy.WriteToServer(table);
34     }
35 }
复制代码

免责声明:文章转载自《EF中的批量操作》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ubuntu 16.04设置rc.local开机启动命令/脚本的方法CSS字体无法设置成功的问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

如何确认 fastboot unlock 解锁成功,如何确认DM-verity 已关闭

如何确认 fastboot unlock 解锁成功 1、fastboot 模式下按音量上键后是否提示 Unlock Pass...return to fastboot in 3s 2、重启后界面是否显示 orange state Your deivce has been unlocked and can't be trusted your device w...

windows-System权限获取任意用户权限目录-举例GetTempPath

目录 一丶简介 二丶代码 一丶简介 在System权限启动我们的程序之后.如果程序内部使用了GetTempPath()函数.或者使用了其它跟用户权限有关的函数.则获取的路径不是你想要的.比如 你在System权限下使用了GetTempPath() 那么获取的temp路径有可能就是 "C:WindowsTemp" 而我们想要获取的路径则是 "C:...

deb包的2种安装安装方法

一、cydia重启自动安装:用ifunbox进入//var/root/Media/Cydia/AutoInstallCydia/AutoInstall 需要分别单独建立,注意大小写。然后把你要安装的deb 拖入此目录,重启两次机器进行安装。 二、iFile安装:把deb包用ifunbox传到//var/mobile/Documents下。打开iFile软件...

如何优雅的在java中统计代码块耗时

如何优雅的在java中统计代码块耗时 在我们的实际开发中,多多少少会遇到统计一段代码片段的耗时的情况,我们一般的写法如下 long start = System.currentTimeMillis(); try { // .... 具体的代码段 } finally { System.out.println("cost: " + (Syste...

dhtmlxscheduler使用

如何和数据库实现交互?增加,删除,修改? 增加,删除 ,修改的实现需要通过dhtmlxscheduler事件来实现,实现模板如下(注意需要引入prototype.js文件): scheduler.attachEvent("onBeforeEventDelete", function(event_id, event_object){     var url...

H5手机开发锁定表头和首列(惯性滚动)解决方案

前端时间移动端在做表格的时候需要这个功能,由于还有实现类似原生的惯性滚动功能,于是使用了iscroll插件。 iscroll插件下载地址:iscroll5 该功能demo github地址:https://github.com/lyc152/front-special-effects/tree/master/table-fixed 下面看下代码结构: HT...