zoukankan      html  css  js  c++  java
  • WCF如何正确调用LINQ TO SQL更新操作

    WCF如何正确调用LINQ TO SQL--更新操作

         上一篇讲到WCF如何正确调用LINQ TO SQL,只涉及到了新增记录的操作。到于为什么要把更新操作分开来讲呢?因为更新确实有点麻烦,相对于新增操作来说,稍微有点难。
         还是使用上一篇的项目,没有源码的兄弟可以到这里下载上一篇的项目:https://files.cnblogs.com/viter/WCF.rar
    首先我们新建一个WinForm窗体UpdateForm,在客户端界面添加一个DataGridView,用来存储从服务读取到的数据,命名为:dgvPurchaseOrder,并在代码中设置自动生成列为False。其实用BindingSource更快,呵呵。
         那好,还是使用BindingSource,不过这个BindingSource是自定义的,因为用来做数据显示控制没有比它更称职的了。


            private BindingSource bdsOrder = new BindingSource();
            
    private
     PurchaseOrderHeader purchaseOrderHeader;

            
    public
     UpdateOrderForm()
            {
                InitializeComponent();
                bdsOrder.CurrentChanged 
    += new
     EventHandler(bdsOrder_CurrentChanged);
            }

    为这个BindingSource定义一个事件,就是BindingSource的CurrentChanged事件。
    这个事件里的代码如下,很简单。

    CurrentChanged


    在界面加载的事件从服务器调取数据
      

    client

         现在我们的数据出来了,好,我们修改一下订单总额,提交到服务器。
    我们将出错信息写到控制台,好好欣赏一下吧,呵呵。好像是真的一样。


         为什么会出现这个错误?我们还是来调试一下,看得更仔细点。

         

         看,好像告诉我们,你要修改的数据已经存在,不能添加。想想有点不妥啊!非常不妥,我不是要添加数据,是要修改数据,为什么会提示“无法附加已经存在的实体”?好,注意看,MS用词还是很恰当的,看这一句:“无法附加已经存在的实体”,注意,是实体!!!那意思是我们的操作没有任何的问题,是实体出了问题,再想一下,我们的实体是通过什么方式来取得的呢?你肯定在电光火石之间想到了,是DataContext,对,是数据上下文,如果你对单张表进行操作,我敢保证你一辈子也不会遇上这个异常,真的不会。好了,现在我们来看下数据库关系图

         这两张表是有关联的,不是独立的表。可能这样还是有点看不明白,不要紧,再看一下生成的DBMl文件。
    PurchaseOrderHeader类里面有一个属性


    private EntitySet<PurchaseOrderDetail> _PurchaseOrderDetail;
    [Association(Name
    ="PurchaseOrderHeader_PurchaseOrderDetail", Storage="_PurchaseOrderDetail", OtherKey="PurchaseOrderHeaderId"
    )]
      [DataMember(Order
    =6, EmitDefaultValue=false
    )]
      
    public EntitySet<PurchaseOrderDetail>
     PurchaseOrderDetail
      {
       
    get

       {
        
    if ((this.serializing 
           
    && (this._PurchaseOrderDetail.HasLoadedOrAssignedValues == false
    )))
        {
         
    return null
    ;
        }
        
    return this
    ._PurchaseOrderDetail;
       }
       
    set

       {
        
    this._PurchaseOrderDetail.Assign(value);
       }
      }

    相对的,PurchaseOrderDetail类里面也有一个对应的属性,用来关联


    private EntityRef<PurchaseOrderHeader> _PurchaseOrderHeader;
    [Association(Name
    ="PurchaseOrderHeader_PurchaseOrderDetail", Storage="_PurchaseOrderHeader", ThisKey="PurchaseOrderHeaderId", IsForeignKey=true
    )]
      
    public
     PurchaseOrderHeader PurchaseOrderHeader
      {
       
    get

       {
        
    return this._PurchaseOrderHeader.Entity;
       }
       
    set

       {
        PurchaseOrderHeader previousValue 
    = this._PurchaseOrderHeader.Entity;
        
    if (((previousValue !=
     value) 
           
    || (this._PurchaseOrderHeader.HasLoadedOrAssignedValue == false
    )))
        {
         
    this
    .SendPropertyChanging();
         
    if ((previousValue != null
    ))
         {
          
    this._PurchaseOrderHeader.Entity = null
    ;
          previousValue.PurchaseOrderDetail.Remove(
    this
    );
         }
         
    this._PurchaseOrderHeader.Entity =
     value;
         
    if ((value != null
    ))
         {
          value.PurchaseOrderDetail.Add(
    this
    );
          
    this._PurchaseOrderHeaderId =
     value.PurchaseOrderHeaderId;
         }
         
    else

         {
          
    this._PurchaseOrderHeaderId = default(int);
         }
         
    this.SendPropertyChanged("PurchaseOrderHeader"
    );
        }
       }
      }

    可以看到,这两个属性是标记数据库两张表的一对多的关系。
    那么我们分析一下,在我们从数据库检索数据的时候,这个关系是否存在?答案是肯定的!
    不好意思,这个图切不下来,各位可以在这里设置断点查看


         通过这里可以看到,关系是存在的,只是由于Linq的延迟加载的特性,数据并没有读取出来而已。
    那么我们就要问了,在查询的时候会有关系,那么向数据库添加数据的时候呢?看一下下面的表格,已经有很好的答案


         好了,既然要关系,我们就加一个试试,在这之前你需要引用System.Data.Linq.dll,并引用System.Data.Linq命名空间。
    加关系很简单,在原来的Update方法里面加一个判断就可以了,如果是修改或删除的操作,那么我们就给它加上关系。
    1~~*和*~~1的关系设置不一样,注意代码里面的设置。


    #region 添加订单头
                        
    //设置行最后修改时间
                     foreach (var item in purchaseOrderHeaderList)
                     {
                         
    //如果是新增或者是删除操作,则设置关系

                         if (item.CurrentStatus == EntityStatus.Update || item.CurrentStatus == EntityStatus.Delete)
                         {
                             
    //一对多的关系

                             item.PurchaseOrderDetail = default(EntitySet<PurchaseOrderDetail>);
                         }
                         item.ModifiedDate 
    =
     DateTime.Now;
                     }
                     result 
    = Common<PurchaseOrderHeader, PurchaseOrderDetail>.GenericUpdate(purchaseOrderHeaderList, "PurchaseOrderDetail"
    , PurchaseTable.PurchaseOrderDetail);
                        
    #endregion


                     
    #region //添加订单细目
                     
    foreach (var headeritem in purchaseOrderHeaderList)
                     {
                         
    if (headeritem.PurchaseOrderDetails != null
    )
                         {
                             
    foreach (var detailitem in
     headeritem.PurchaseOrderDetails)
                             {
                                 
    //如果是新增或者是删除操作,则设置关系

                                 if (detailitem.CurrentStatus == EntityStatus.Update || detailitem.CurrentStatus == EntityStatus.Delete)
                                 {
                                     
    //多对一的关系

                                     detailitem.PurchaseOrderHeader = new PurchaseOrderHeader() { PurchaseOrderHeaderId = detailitem.PurchaseOrderHeaderId };
                                 }
                                 
    //订单头添加完成后,将会产生一个新的PurchaseOrderHeaderId

                                 detailitem.PurchaseOrderHeaderId = headeritem.PurchaseOrderHeaderId;
                                 
    //设置行最后修改时间

                                 detailitem.ModifiedDate = DateTime.Now;
                                 detailList.Add(detailitem);
                             }
                         }
                     }
                     
    #endregion

                     


    好,我们现在来修改订单编号为1的记录,将订单总额改为5000.

    成功!


     

    欢迎转载,但请注明出处--梁规晓博客(http://www.cnblogs.com/viter/)!
    下一篇将介绍“如何将WCF和WF无缝的结合”。谢谢大家的关注!

    点击下面下载服务端和客户端源代码.

    https://files.cnblogs.com/viter/WCF2.rar

    说得不对的地方,欢迎拍砖!

  • 相关阅读:
    在VirtualBox安装debian8.8(完整版)
    Ubuntu18.04 离线安装 docker
    基于JWT的Token认证机制及安全问题
    BTree
    ConcurrentHashMap原理
    Utf8BomRemover
    Spring源码下载
    【intellij idea】Project Structure 讲解 Ctrl+Alt+Shift+S
    idea使用过程中, maven包已经正常下载,但是项目中依然无法引入,提示不存在
    java正则判断字符串是否含有中文、数字、字母
  • 原文地址:https://www.cnblogs.com/dudu837/p/1549838.html
Copyright © 2011-2022 走看看