加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

在Entity Framework中使用存储过程(四):如何为Delete存储过程

发布时间:2020-12-16 09:05:47 所属栏目:asp.Net 来源:网络整理
导读:继续讨论EF中使用存储过程的问题,这回着重讨论的是为存储过程的参数进行赋值的问题。说得更加具体一点,是如何为实体映射的Delete存储过程参数进行赋值的问题。关于文中涉及的这个问题,我个人觉得是EF一个有待改进的地方,不知道各位看官是否同意? 目录

继续讨论EF中使用存储过程的问题,这回着重讨论的是为存储过程的参数进行赋值的问题。说得更加具体一点,是如何为实体映射的Delete存储过程参数进行赋值的问题。关于文中涉及的这个问题,我个人觉得是EF一个有待改进的地方,不知道各位看官是否同意?

目录
一、EF存储过程参数赋值的版本策略
二、Delete存储参数就一定是Original值吗?
三、如果直接修改.edmx模型的XML呢?
四、为Delete存储过程参数赋上Current值,如何做得到?

一、EF存储过程参数赋值的版本策略

和传统的基于DataSet的ADO.NET类似,EF的核心功能之一就是“状态追踪(State Tacking)”。这中间实际上又涉及到两个方面:通过状态决定数据更新的类型(Insert、Update和Delete);以及同时保存不同版本的属性值(Current值和Original值)。版本策略主要是针对Update操作设计的,一般来讲组成Where条件的为Original值,而更新的值为Current值。

正是因为只有Update操作才需要显式指定映射的是实体属性值的版本(Current/Original),所以在进行实体/存储过程映射的时候,只有Update存储过程才可以选择“是否采用原始值(Use Original Value)”。Insert和Delete存储过程默认的版本为Current和Original。反映在VS的.edmx模型设计器上就是:只有Update存储过程的参数映射才具有“Use Original Value”这个复选框

二、Delete存储参数队应的就一定是Original值吗?

粗略地想想,EF这样设计也无可厚非:Insert存储过程用于添加一条全新的记录,自然应该采用当前值;而Delete存储过程用于删除一条现有的记录,删除操作的筛选条件自然应该使用原始值。但是,我们忽略掉一点:Delete存储过程一定非得执行删除操作吗?如果我进行“逻辑删除”,实际上进行的是Update操作。关于逻辑删除的实现,可以参阅我上一篇文章《逻辑删除的实现与自增长列值返回》。

如果你看了我提到的这篇文章,你可能会问,即使在文中介绍的关于“逻辑删除”的场景中,也没有使用当前值得要求呀。是的,上一篇文章提到的逻辑删除确实也只需要传入实体属性的原始值作为Delete存储过程的参数,现在我们就举一个这样的例子。

通过是使用T_CONTACT这张简单不过的表,同样是采用逻辑删除。不过现在有这样的一个要求,对于条存储在的记录,我们需要记录最后修改者是谁。对于一条被逻辑删除掉的记录,这个最后修改者就是删除掉该条记录的人。这是一个很常见的需求,为此我们可以直接在T_CONTACT的数据表中添加一个新的字段:LAST_UPDATED_BY,创建该表的DDL定义如下:

   1: CREATE TABLE [T_CONTACT]
   3:     [ID]                [INT] IDENTITY(1,1)   PRIMARY KEY,
   5:     [IS_DELETED]        [BIT]                    6:     [LAST_UPDATED_BY]   [NVARCHAR](50)        NULL
    
   3:  @p_id INT,1)" id="lnum4">   4:  @user_name NVARCHAR(50)
   6: AS
   8:     UPDATE    T_CONTACT
  11:     WHERE     ID = @p_id
<EntityTypeMapping TypeName="EFExtensionsModel.Contact">
   3:     InsertFunction FunctionName="EFExtensionsModel.Store.P_CONTACT_I"    4:       ScalarProperty Name="LastUpdatedBy" ParameterName="user_name" />
   6:       ResultBinding ="ID" ColumnName="ID"    7:     </InsertFunctionUpdateFunction ="EFExtensionsModel.Store.P_CONTACT_U"    9:       ="user_name" Version="Current"   10:       ="p_name"   11:       ="p_id" ="Original"   12:     UpdateFunction  13:     DeleteFunction ="EFExtensionsModel.Store.P_CONTACT_D"   14:         15:       ="p_id"   16:     DeleteFunction  17:     18: EntityTypeMapping>

那些现在我们将DeleteFunction的user_name参数的映射节点人为地加上Version=“Current”属性设置。

property versions.”

四、为Delete存储过程参数赋上Current值,如何做得到?

从上面的介绍我们不难发现,Delete存储过程不能接受基于当前值得参数映射,并不仅仅是设计器不支持,EF本来就是这样设计的。在这种情况下要实现我们的要求,只有一个办法:将当前值转化成初始值值,这样的转变通过调用ObjectContext的AcceptAllChanges方法可以实现。具体来说,对于需要删除的实体,现设定LastUpdatedBy属性,然后调用AcceptAllChanges方法,然后再调用ObjectStateManager的ChangeObjectState方法将状态设置为Deleted。最终通过调用SaveChanges方法提交更新,具体的代码如下: