zoukankan      html  css  js  c++  java
  • Entity Framework4.0 (七) EF4的存储过程

    前面了解了EF4的CRUD的操作,你会发现EF4使用起来比较简单的。呵呵,之前我们使用数据库的时候,有时会使用存储过程代替在代码中直接使用SQL语句。

    使用存储过程的好处:

    • 提高效率:因为存储过程是经过编译优化后,存储在数据库服务器的。SQL语句在执行的时候,需要临时编译。一般来说,存储过程的效率比SQL语句效率高。
    • 降低日后维护的难度:因为对存储过程的修改不需要修改应用程序代码。我们在程序代码中直接调用的是存储过程名字,和参数列表(如果是带参数的存储过程),在维护的时候,可以不修改存储过程的名字和参数列表,而是修改存储过程的具体实现细节,从而达到维护的目的。

    我们首先来创建几个Category存储过程:

    1. 打开SQL server2008 Management Studio,我们使用Northwind 数据库。

    依次展开节点,如下图:

    此时打开新建存储过程的窗口如下图:

    上面图中已经标出有三部分:1.存储过程名字。 2. 存储过程参数。3.存储过程体。只要补充这三部分,然后执行脚本,就创建了该存储过程。

    我们先添加一个插入Category的存储过程,代码如下:

     1 SET ANSI_NULLS ON
    2 GO
    3 SET QUOTED_IDENTIFIER ON
    4 GO
    5 -- =============================================
    6 -- Author: <Author,,Name>
    7 -- Create date: <Create Date,,>
    8 -- Description: <Description,,>
    9 -- =============================================
    10 CREATE PROCEDURE InsertCategory
    11 -- Add the parameters for the stored procedure here
    12 @cateName varchar(15),
    13 @cateDesc ntext
    14 AS
    15 BEGIN
    16 -- SET NOCOUNT ON added to prevent extra result sets from
    17 -- interfering with SELECT statements.
    18 SET NOCOUNT ON;
    19
    20 -- Insert statements for procedure here
    21 insert into dbo.Categories (CategoryName,Description)values(@cateName,@cateDesc)
    22 END
    23 GO

    (小技巧:在你写表名和列名的名字的时候,名字太长,不方便的话。你可以直接使用鼠标左键拖拽表名或列名到右边的编辑窗口,然后松开鼠标即可。)

    好了,InertCategory这个存储过程的创建脚本已经写完,然后,我们执行下该存储过程的。如果在下面的提示框中有:Command(s) completed successfully.,则表示创建成功,然后“刷新左边,就会发现已经创建的存储过程已经出现了”如下图:

    在新建的存储过程上右键,可以修改、或执行该存储过程。我们选择执行。如下图

    点击“OK”,成功以后,查看数据库,新记录已经插入成功。

    同样的方式,我们创建删除Category的存储过程:DeleteCategory,代码如下:

     1 SET ANSI_NULLS ON
    2 GO
    3 SET QUOTED_IDENTIFIER ON
    4 GO
    5 -- =============================================
    6 -- Author: <Author,,Name>
    7 -- Create date: <Create Date,,>
    8 -- Description: <Description,,>
    9 -- =============================================
    10 CREATE PROCEDURE DeleteCategory
    11 -- Add the parameters for the stored procedure here
    12 @cateID int
    13 AS
    14 BEGIN
    15 -- SET NOCOUNT ON added to prevent extra result sets from
    16 -- interfering with SELECT statements.
    17 SET NOCOUNT ON;
    18
    19 -- Insert statements for procedure here
    20 delete from dbo.Categories where CategoryID =@cateID
    21 END
    22 GO

    我们创建更新Category的存储过程:DeleteCategory,代码如下:

     1 SET ANSI_NULLS ON
    2 GO
    3 SET QUOTED_IDENTIFIER ON
    4 GO
    5 -- =============================================
    6 -- Author: <Author,,Name>
    7 -- Create date: <Create Date,,>
    8 -- Description: <Description,,>
    9 -- =============================================
    10 CREATE PROCEDURE UpdateCategory
    11 -- Add the parameters for the stored procedure here
    12 @cateID int,
    13 @cateName nvarchar(15),
    14 @cateDesc ntext
    15 AS
    16 BEGIN
    17 -- SET NOCOUNT ON added to prevent extra result sets from
    18 -- interfering with SELECT statements.
    19 SET NOCOUNT ON;
    20
    21 -- Insert statements for procedure here
    22 update dbo.Categories set CategoryName =@cateName, Description=@cateDesc
    23 where CategoryID=@cateID
    24 END
    25 GO

    我们创建选择Category的存储过程:DeleteCategory,代码如下:

     1 SET ANSI_NULLS ON
    2 GO
    3 SET QUOTED_IDENTIFIER ON
    4 GO
    5 -- =============================================
    6 -- Author: <Author,,Name>
    7 -- Create date: <Create Date,,>
    8 -- Description: <Description,,>
    9 -- =============================================
    10 CREATE PROCEDURE SelectCategory
    11 -- Add the parameters for the stored procedure here
    12
    13 AS
    14 BEGIN
    15 -- SET NOCOUNT ON added to prevent extra result sets from
    16 -- interfering with SELECT statements.
    17 SET NOCOUNT ON;
    18
    19 -- Insert statements for procedure here
    20 SELECT * from dbo.Categories
    21 END
    22 GO

    好了,我们就创建这些存储过程。
    2.我们创建一个项目,来通过EF4使用这些存储过程。

    打开visual studio2010,创建windows form应用程序:EFStoredProcedureDemo.

    在项目:EFStoredProcedureDemo上面右键--》添加新项,选择:Ado.net Entity Data Model,名称:Northwind,

    然后点下一步:此时点击“New Connection” 找数据库服务器,再找到Northwind数据库。如下图:

    点击下一步:

    在tables里选择Category,如下图:

    在Stored Procedure里面选择刚才创建的四个存储过程。

    选中“Pluralize or singularize generated object names”和“Include foreign key columns in the model”, 点击finish.生成*.edmx,并自动打开设计视图:

    在设计器选中实体Category,点击右键:选择Table Mapping .在Mapping 窗口中有两项:Mapping entity to tables和Mapping entity to Functions。选择Mapping entity to Functions,如下图:

    存储过程的参数也要对应起来:最终结果如下图:

     好的,现在我们就把更新、删除、插入的存储过程与EDM的函数对应起来了。还有一个比较特殊的是就是选择的存储过程。

    下面我们来映射SelectCategory存储过程。

    在EDM设计器的空白处:右键--》Model Browser,打开Model 浏览窗口。如下图:

    在SelectCategory上面右键->Add Function Import...如下图:

    Function Import Name是引入后,在代码中使用时所用到的名字。然后返回值的集合,选择:实体(Category),如下图:然后点击OK

    此时我们在Model Browser 中看到我们已经成功引用一个函数:如下图:

    3. 下面我们来使用这个作了存储过程映射的EDM,在Form1上添加控件如下图:(因为在写代码的时候,都是通过访问其Name属性来找到该控件的。所以,我把文本框控件的显示文本初始化为其Name,这样既方便了自己编程,也方便了大家阅读代码。)

    FillListbox 用于填充数据到listbox,click事件代码如下:

     1  private void button1_Click(object sender, EventArgs e)
    2 {
    3 using(var context = new NorthwindEntities())
    4 {
    5 //var categories = from c in context.Categories
    6 // select new {c.CategoryID,c.CategoryName};
    7
    8 var categories = context.SelectCategory();
    9
    10 this.listBox1.DisplayMember = "CategoryName";
    11 this.listBox1.ValueMember = "CategoryID";
    12 this.listBox1.DataSource = categories;
    13 }
    14 }

    注意:上面注释掉的部分,是我们以前使用的方式。现在的context调用了一个方法:SelectCategory()。它就是刚才我们用selectCategory存储过程映射成的那个函数。SelectCategory()在调用的时候,最终是执行低层的selectCategory存储过程的。

    添加功能。代码如下:

     1    private void btnInsert_Click(object sender, EventArgs e)
    2 {
    3 using (var context = new NorthwindEntities())
    4 {
    5 Category c = new Category();
    6 c.CategoryName = this.tbCateNameNew.Text.ToString().Trim();
    7 c.Description = this.tbCateDescNew.Text.ToString().Trim();
    8
    9 context.AddToCategories(c);
    10 context.SaveChanges();
    11 MessageBox.Show("succeed");
    12 }
    13 }

    更新功能,代码如下:

     1   private void btnUpdate_Click(object sender, EventArgs e)
    2 {
    3 int id =Convert.ToInt32(this.tbCateIDUpdate.Text);
    4
    5 using (var context = new NorthwindEntities())
    6 {
    7 var categories = context.Categories.First(c=>c.CategoryID == id);
    8
    9 categories.CategoryName = this.tbNameUpdate.Text.ToString().Trim();
    10 categories.Description = this.tbDescUpdate.Text.ToString().Trim();
    11 context.SaveChanges();
    12 MessageBox.Show("succeed");
    13 }
    14 }

    删除功能,代码如下:

     1  private void btnDele_Click(object sender, EventArgs e)
    2 {
    3 int id = Convert.ToInt32(this.tbCateID.Text);
    4
    5 using (var context = new NorthwindEntities())
    6 {
    7 var categorie = context.Categories.First(c => c.CategoryID == id);
    8 context.DeleteObject(categorie);
    9
    10 context.SaveChanges();
    11 MessageBox.Show("succeed");
    12 }
    13 }

    从上面可以看到,使用了存储过程以后,我们作增删改的代码,并没有任何变化。只有选择有些变化。以前我们没有映射存储过程,所以LINQ语句最终是生成SQL脚本现在我们使用了存储过程以后,再执行上面这些代码时,最终都是映射成调用数据库的存储过程,而不再生成脚本了。如果有Data profile viewer的话,你可以监控观察数据库的执行情况,可惜我机器上没有,所以无法截图了。

    存储过程在EF4中是当作函数来处理的。

    可以打开EDM的xml的形式查看:和没有映射存储过程以前,发现有以下变化。

    SSDL部分:

     1    <Function Name="DeleteCategory" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
    2 <Parameter Name="cateID" Type="int" Mode="In" />
    3 </Function>
    4 <Function Name="InsertCategory" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
    5 <Parameter Name="cateName" Type="varchar" Mode="In" />
    6 <Parameter Name="cateDesc" Type="ntext" Mode="In" />
    7 </Function>
    8 <Function Name="SelectCategory" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" />
    9 <Function Name="UpdateCategory" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
    10 <Parameter Name="cateID" Type="int" Mode="In" />
    11 <Parameter Name="cateName" Type="nvarchar" Mode="In" />
    12 <Parameter Name="cateDesc" Type="ntext" Mode="In" />
    13 </Function>

    CSDL部分:

    1      <FunctionImport Name="SelectCategory" EntitySet="Categories" ReturnType="Collection(NorthwindModel.Category)" />

    Mapping部分分两部分映射:

     1     <ModificationFunctionMapping>
    2 <InsertFunction FunctionName="NorthwindModel.Store.InsertCategory" >
    3 <ScalarProperty Name="Description" ParameterName="cateDesc" />
    4 <ScalarProperty Name="CategoryName" ParameterName="cateName" />
    5 </InsertFunction>
    6 <UpdateFunction FunctionName="NorthwindModel.Store.UpdateCategory" >
    7 <ScalarProperty Name="Description" ParameterName="cateDesc" Version="Current" />
    8 <ScalarProperty Name="CategoryName" ParameterName="cateName" Version="Current" />
    9 <ScalarProperty Name="CategoryID" ParameterName="cateID" Version="Current" />
    10 </UpdateFunction>
    11 <DeleteFunction FunctionName="NorthwindModel.Store.DeleteCategory" >
    12 <ScalarProperty Name="CategoryID" ParameterName="cateID" />
    13 </DeleteFunction>
    14 </ModificationFunctionMapping>
    1   <FunctionImportMapping FunctionImportName="SelectCategory" FunctionName="NorthwindModel.Store.SelectCategory" />

    在概念层EF4并不直接和存储过程打交到。而是以函数的形式处理实体。这样更符合面向对象的编程形式。

    存储过程结合EF4的使用,是很方面的。可以有人专门设计存储过程,而由其它人使用的时候,只是使用映射过后的函数。这样就更加直观。调用时也不必考虑底层存储过程的形式了。

    好了,就到这了。晚安咯!!!
     

  • 相关阅读:
    链表 | 将递增有序的两个链表的公共元素合并为新的链表
    链表 | 将两个递增链表合并为一个递减链表
    雪花特效
    vuex笔记
    Vue路由
    Vue框架使用sass
    vue组件通信
    vue请求数据
    07_06.哈夫曼树
    07_05.通过链接实现二叉树及其遍历
  • 原文地址:https://www.cnblogs.com/marksun/p/2296500.html
Copyright © 2011-2022 走看看