项目结构:

1.客户端:Winform,

2.数据访问:EF4.0(从数据库生成模型-懒人必需这样)

3.DTO:直接使用EF实体

4.服务端:WCF 托管在IIS中采用basicHttp帮定(这样可以客户端的代理类就不需要每次人肉释放了)

Winform或asp.net ,MVC中每次一般只操作一条记录或者对多条记录进行相同的操作,这个时候我们知道需要对记录或记录集合进行的是那种CURD.

但是如果直接将获取的记录集合 List<T> 帮定到BindingSource并关联DataGridView(或gridControl),并且使用gridControl提供的CURD功能时,怎么才能知道那些记录需要进行那些CURD操作呢?
解决方案暂时不提,  凭借gridcontrol提供的强大功能,一般的单个数据表CRUD可以直接拖控件完成,要知道在一般的企业项目中有大量的基础数据收集维护功能,尤其当你是一个人在战斗时,能拖个控件就把CURD完成时是多么的有幸福,而且现在是采用标准的三层结构,你可以对服务层做下反向代理以实现负载均衡了。

解决办法

界面如下

EF默认在Context中保存对象的状态,但是当对象通过WCF传输后,我们在两端获取对方传输过来的对象多是Detached状态,而且在客户端典型的用法是直接将List<T>帮定到BindingSrouce上,根本不使用EFContext对象进行跟着。

1.那么解决首先是要在客户端对List<T>的对象进行跟踪    要进行跟踪懒人加吊丝的做法当然不是自己实现EF跟踪接口,而是直接使用EFContext对象,    那客户端EFContext对象直接SaveChanges连数据库怎么办?    参考下面的配置,将EF连接字符串的关键信息全部换成*,这样你就能在WinForm中正常的New出Context对象了

  <add name="FireSeatEntities" connectionString="metadata=res://*/FireSeatDB.csdl|res://*/FireSeatDB.ssdl|res://*/FireSeatDB.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=****;initial catalog=****;persist security info=True;user id=****;password=***;multipleactiveresultsets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

2.将服务端加载对象添加到Context环境中 2.1.首先是第一次加载,一般是由一个查询引起的

                var dicItems= Fetch<IDicItemsService>().Take(0,100,string.Format("it.DicNo='{0}'", cur.DicNo), "it.OrderId");
foreach (var item in dicItems)
{
EntCtx.Attach(item); //这里进行附加
}
//绑定到BindingSource
sys_DicItemsBindingSource.DataSource = dicItems;

2.2.对gridControl进行的添加擅长操作做提示并关联到Context

            dataNavigator1.ButtonClick += (s, ie) => {
try
{
#region
if (ie.Button.ButtonType == NavigatorButtonType.Append)
{
var dicNo = dicNoTextEdit.Text.Trim();
if (string.IsNullOrWhiteSpace(dicNo)) throw new Exception("请输入字典编号!"); var cur = sys_DicItemsBindingSource.AddNew() as Sys_DicItems;
cur.DicNo = dicNo;
EntCtx.CreateObjectSet<Sys_DicItems>().AddObject(cur); ie.Handled = true;
} else if (ie.Button.ButtonType == NavigatorButtonType.Remove)
{
var cur = sys_DicItemsBindingSource.Current as Sys_DicItems;
if ( MessageBox.Show("确认删除吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.Cancel)
{
ie.Handled = true;
return;
} EntCtx.DeleteObject(cur); }
else if (ie.Button.ButtonType == NavigatorButtonType.EndEdit)
{
gridView1.CloseEditor();
}
#endregion
}
catch (Exception ex)
{
ie.Handled = true;
ErrMsg(ex.Message);
}
};

2.3.对gridcontrol 进行 大量 添加,修改,删除后点保存

         gridView1.CloseEditor();
sys_DicItemsBindingSource.EndEdit(); //获取进行了CUD的记录集合
var addList = EntCtx.ObjectStateManager.GetObjectStateEntries(EntityState.Added).Select(osEnt => osEnt.Entity as Sys_DicItems).ToList();
var delList = EntCtx.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted).Select(osEnt => osEnt.Entity as Sys_DicItems).ToList();
var editList = EntCtx.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).Select(osEnt => osEnt.Entity as Sys_DicItems).ToList(); #region 更新字典条目 EntityUpdateSet<Sys_DicItems> retDs = null;
Action act = () =>
{
var ds = new EntityUpdateSet<Sys_DicItems>(addList, delList, editList) {ReturnAddList=true,ReturnEditList=true };
retDs = Fetch<IDicItemsService>().BatchUpdate(ds);
}; InvokeService(act, "更新列表"); //将服务器返回记录归并到本地
for (int i = 0; i < retDs.AddList.Count; i++)
{
CloneEFModel<Sys_DicItems, Sys_DicItems>(retDs.AddList[i], addList[i]);
}
for (int i = 0; i < retDs.EditList.Count; i++)
{
CloneEFModel<Sys_DicItems, Sys_DicItems>(retDs.EditList[i], editList[i]);
} //将所以记录设置成Unchange状态
EntCtx.AcceptAllChanges();
sys_DicItemsBindingSource.ResetBindings(false);

3.服务端的定义

EntityUpdateSet定义了CUD操作对应的列表

    public class EntityUpdateSet<T>
where T : System.Data.Objects.DataClasses.EntityObject
{
public EntityUpdateSet()
{
AddList = new List<T>();
ReturnAddList = true;
DelList = new List<T>();
ReturnDelList = false;
EditList = new List<T>();
ReturnEditList = false;
}
public EntityUpdateSet(List<T> addList, List<T> delList, List<T> editList):this()
{
this.AddList = addList;
this.DelList = delList;
this.EditList = editList;
}
public List<T> AddList { get; set; }
public bool ReturnAddList { get; set; }
public List<T> DelList { get; set; }
public bool ReturnDelList { get; set; }
public List<T> EditList { get; set; }
public bool ReturnEditList { get; set; } }

具体的操作,这个应该都清楚了

        public EntityUpdateSet<T> BatchUpdate(EntityUpdateSet<T> ds)
{
BatchUpdateVerify(ds);
var set = Ctx.CreateObjectSet<T>();
foreach (var addItem in ds.AddList)
{
set.AddObject(addItem);
}
foreach (var delItem in ds.DelList)
{
set.Attach(delItem);
set.DeleteObject(delItem);
}
foreach (var editItem in ds.EditList)
{
set.Attach(editItem);
Ctx.ObjectStateManager.ChangeObjectState(editItem, System.Data.EntityState.Modified);
}
Ctx.SaveChanges();
if (!ds.ReturnAddList) ds.AddList.Clear();
if (!ds.ReturnDelList) ds.DelList.Clear();
if (!ds.ReturnEditList) ds.EditList.Clear(); return ds; }

最后很最重要的一点是:在关闭窗体后需要释放对象,不然大量数据加长时间运行会导致客户端内存泄露的

protected override void OnClosed(EventArgs e)

{

base.OnClosed(e);

sys_DicItemsBindingSource.Dispose();

sys_DicBindingSource.Dispose();

if (EntCtx != null) EntCtx.Dispose();

}

最后之最后,最最总要的一点是,NND即使使用了上面的释放代码,内存一样只增不减,那位兄弟帮忙解决下啊 (首先排除是WCF代理对象未释放问题,Fetch<IDicItemsService> 获取缓存的代理对象,进行不停调用,不会出现内存问题,只有把EFModel attch到客户端的Context时才出现问题)

Devexpress + wcf +ef 批量更新处理的更多相关文章

  1. EF 批量更新删除(linq篇)

    刚开始用EF很多东西都不会用,事后想想都很简单的东西总是用很麻烦的方式实现 1:  EF的联合查询 inner join  很久很久以前我是这么写一个列表展示的,其中有两个字段Contractor和M ...

  2. 【转】Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)

    E文好的可以直接看https://github.com/loresoft/EntityFramework.Extended 也可以在nuget上直接安装这个包,它的说明有点过时了,最新版本已经改用对I ...

  3. (转)Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)

    转自:http://www.cnblogs.com/jinzhao/archive/2013/05/31/3108755.html 今天乍一看,园子里居然没有关于这个类库的文章,实在是意外毕竟已经有很 ...

  4. EF结合SqlBulkCopy实现高效的批量数据插入 |EF插件EntityFramework.Extended实现批量更新和删除

    原文链接:http://blog.csdn.net/fanbin168/article/details/51485969   批量插入 (17597条数据批量插入耗时1.7秒)   using Sys ...

  5. LINQ To SQL在N层应用程序中的CUD操作、批量删除、批量更新

    原文:LINQ To SQL在N层应用程序中的CUD操作.批量删除.批量更新 0. 说明 Linq to Sql,以下简称L2S.    以下文中所指的两层和三层结构,分别如下图所示: 准确的说,这里 ...

  6. EF批量操作数据与缓存扩展框架

    前言 在原生的EF框架中,针对批量数据操作的接口有限,EF扩展框架弥补了EF在批量操作时的接口,这些批量操作包括:批量修改.批量查询.批量删除和数据缓存,如果您想在EF中更方便的批量操作数据,这个扩展 ...

  7. SQL批量更新 关系表更新

    很多人在做数据的批量更新时..如果更新的内容是从其他表查出来的..很容易这么写.. UPDATE TABLE1 SET COLUMN1=(SELECT SUM(SOMETHING) FROM TABL ...

  8. SQL 将2张不相关的表拼接成2列,批量更新至另一张表

    update SO_Master set LotteryNo=t2.LotteryNo,UpdateTime=GETDATE() --select sm.LotteryNo,sm.SysNo,t2.L ...

  9. [PDO绑定参数]使用PHP的PDO扩展进行批量更新操作

    最近有一个批量更新数据库表中某几个字段的需求,在做这个需求的时候,使用了PDO做参数绑定,其中遇到了一个坑. 方案选择 笔者已知的做批量更新有以下几种方案: 1.逐条更新 这种是最简单的方案,但无疑也 ...

随机推荐

  1. mongodb sharding集群搭建

    创建虚拟机,如果是使用copy的方式安装系统,记得修改机器名,否则所有的机器名称都一样,会造成安装失败 同时关闭掉防火墙,将所有的机器的时间调成一致,master和slave的heartbeat间隔不 ...

  2. v4l2框架函数调用关系

    所有的设备节点和子设备节点都是通过__video_register_device()注册的 1.对于video设备节点: 用户空间ioctl(VIDIOC_S_FMT)---> v4l2_fop ...

  3. ballerina 学习十八 事务编程

    事务在分布式开发,以及微服务开发中是比较重要的 ballerina 支持 本地事务.xa 事务.分布式事务 ,但是具体的服务实现起来需要按照ballerian 的事务模型 infection agre ...

  4. 【Xamarin】Visual Studio 2013 Xamarin for Android开发环境搭建与配置&Genymotion

    Xamarin Xamarin是基于Mono的平台. Xamarin旨在让开发者可以用C#编写iOS, Android, Mac应用程序,也就是跨平台移动开发. 下载资源 1,进入Xamarin官方网 ...

  5. Ant build.xml相关属性详解

    关键字: ant build.xml Ant的概念 可能有些读者并不连接什么是Ant以及入可使用它,但只要使用通过Linux系统得读者,应该知道make这个命令.当编译Linux内核及一些软件的源程序 ...

  6. bzoj 5020(洛谷4546) [THUWC 2017]在美妙的数学王国中畅游——LCT+泰勒展开

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5020 https://www.luogu.org/problemnew/show/P4546 ...

  7. 远程连接Linux虚拟机上的mysql失败的解决方法

    今天在虚拟机Ubuntu上折腾了一晚上mysql,然后试着用java连接,搞了很久都没成功,但是同学配好的Debian上却连接成功了,也就是说我的配置有问题. 折腾了很久,最后还是通过理解异常信息来大 ...

  8. 【记录】MVC4中使用SignalR

    前言 周末在偶尔翻阅微软官网的时候看到Getting Started with SignalR and MVC 4此篇文章,知道了signalr这个东西,貌似这个出来很长时间了,奈何自己一直没有发现, ...

  9. 十一.jQuery源码解析之.pushStack()

    pushStack()顾明思意,就是像桟中添加东西呗,现在看看他是如何添加东西的. 创建一个空的jQuery对象,然后把Dom元素集合放入这个jQuery对象中, 并保留对当前jQuery对象的引用. ...

  10. solr常见异常解决办法

    科普篇 来自百度百科:Solr简介Solr是一个基于Lucene的Java搜索引擎服务器.Solr 提供了层面搜索.命中醒目显示并且支持多种输出格式(包括 XML/XSLT 和 JSON 格式).它易 ...