MVC5+EF6 Getting Started Complete Tutorial 4: EF Basic CRUD

The previous article mainly talked about how to configure EF, let's review the main process:

Create Data Model  à  create Database Context  à create databaseInitializer à configure the context configuration section of entityFramework.

If you still have questions about this process, you can go to the previous article and read it again.

This time we will mainly explain (1) EF basic CRUD (2) common HtmlHelper involved

article outline

Overview & Highlights

theoretical basis

detailed steps

Summarize

Overview & Highlights

The following is the main point of this article, and the main text will introduce it in detail.

  • CRUD for EF data model
  • Commonly used HtmlHelper
  • Repository Pattern

Theoretical basis -- EF three programming methods (omitted)

There are three ways in total:

Database First, Model First and Code First, we use code first.

There is a lot of information in this area, so I won’t repeat it. If you need to understand the differences and application scenarios of the three, please refer to other information by yourself.

Theoretical basis -- EF CRUD

Give some typical examples for the previously created SysUser, SysRole, and SysUserRole. You can imitate these examples when using basic CRUD.

The database sample data we will use are as follows:    

SysUser

SysRole

SysUserRole

EF data query

Let's talk about the most frequently used query part first.     

EF data query is implemented with LINQ (LINQ to Entities), usually in two ways: expression and function. It is recommended to use the functional method, which is relatively simple.

Suppose we have defined the context

private AccountContext db = new AccountContext();

  1. [Basic query] Query all SysUsers

    var users = from u in db.SysUsers

    select u; //表达式方式

users = db.SysUsers; //函数式方式

  1. [条件查询] 加入查询条件

    users = from u in db.SysUsers

    where u.UserName == "Tom"

    select u; //表达式方式

    users = db.SysUsers.Where(u => u.UserName == "Tom"); //函数式方式

    NOTE 注意这边等号是C#写法 : " == "

  1. [排序和分页查询]

    users = (from u in db.SysUsers

    orderby u.UserName

    select u).Skip(0).Take(5); //表达式方式

    users = db.SysUsers.OrderBy(u => u.UserName).Skip(0).Take(5); //函数式方式

    NOTE 只有排序了才能分页

  1. [聚合查询]

    //查user总数

    var num = db.SysUsers.Count();

    //查最小ID

 minId = db.SysUsers.Min(u => u.ID);

    NOTE 聚合查询只能通过函数式查询

  1. [连接查询]

    var users = from ur in db. SysUserRoles

    join u in db. SysUsers

    on ur.SysUserID equals u.ID

 ur;

NOTE

大家注意,连接查询返回的结果还是一个类型为SysUserRoles的集合,只是用

了内连接进行了的筛选。

那么问题来了,如果我需要选择一个集合,里面包括多张表,如SysUser里面的UserName和SysRole里面的RoleName怎么办?

这个是通过navigation property来实现的, 前面新建model的时候提到过,例如SysUser里面的

public virtual ICollection<SysUserRole> SysUserRoles { getset; }

但这种做法还是不是太灵活,具体做法我们在下面的详细步骤里面讲。

EF数据更新

UPDATE步骤比较清晰,直接看下面代码。

//数据更新,分三步:找到对象--> 更新对象数据--> 保存更改

public ActionResult EFUpdateDemo()

{

//1.找到对象

var sysUser = db.SysUsers.FirstOrDefault(u => u.UserName == "Tom");

//2.更新对象数据

if (sysUser != null)

{

sysUser.UserName = "Tom2";

}

//3.保存修改

db.SaveChanges();

return View();

}

EF数据添加/删除

与UPDATE类似。

//数据添加和删除

public ActionResult EFAddOrDeleteDemo()

{

//添加

//1.创建新的实体

var newSysUser = new SysUser()

{

UserName = "Scott",

Password = "tiger",

Email = "[email protected]"

};

//2.增加

db.SysUsers.Add(newSysUser);

//3.保存修改

db.SaveChanges();

 

//删除

//1.找到需要删除的对象

var delSysUser = db.SysUsers.FirstOrDefault(u => u.UserName == "Scott");

//2.删除

if (delSysUser!=null)

{

db.SysUsers.Remove(delSysUser);

}

//3.保存修改

db.SaveChanges();

return View("EFQueryDemo");

}

详细步骤

  • 查询用户及相应角色的功能
  • 修改用户
  • 增加用户和删除用户

查询用户及相应的角色

  1. 在Controller中修改Index方法,添加相关View, 显示所有用户
    1. 将model作为参数传过去

    2. Views à Account à Index.cshtml 顶部添加强类型声明,

      @model IEnumerable<MVCDemo.Models.SysUser>

      body中添加个table用来显示数据

      NOTE

      @Html.ActionLink("Details""Details"new { id = item.ID })生成一个相同controller下的路由地址。

      显示结果

       

  2. 增加一个Details方法,添加相关View, 显示相应用户及对应的角色
    1. 将特定的model传过去

       

    2. Views à Account à Index.cshtml 顶部添加强类型声明

      @model MVCDemo.Models.SysUser

      显示数据,注意方框部分如何导航到另外一张表的信息中。

      显示结果

       

更新用户,增加用户,删除用户

这三个操作都类似,属于更新的范畴,我们放在一起来讲。

  1. 修改Views à Account à Index.cshtml

    开头增加Create链接。

    table每条记录后面增加Edit,Delete链接。

     

  2. 在Controller中增加相应的方法。

    新建用户:

//新建用户

public ActionResult Create()

{

return View();

}

[HttpPost]

public ActionResult Create(SysUser sysUser)

{

db.SysUsers.Add(sysUser);

db.SaveChanges();

return RedirectToAction("Index");

}

修改用户:

//修改用户

public ActionResult Edit(int id)

{

SysUser sysUser = db.SysUsers.Find(id);

return View(sysUser);

}

[HttpPost]

public ActionResult Edit(SysUser sysUser)

{

db.Entry(sysUser).State = EntityState.Modified;

db.SaveChanges();

return RedirectToAction("Index");

}

删除用户:

//删除用户

public ActionResult Delete(int id)

{

SysUser sysUser = db.SysUsers.Find(id);

return View(sysUser);

}

[HttpPostActionName("Delete")]

public ActionResult DeleteConfirmed(int id)

{

SysUser sysUser = db.SysUsers.Find(id);

db.SysUsers.Remove(sysUser);

db.SaveChanges();

return RedirectToAction("Index");

}

NOTE

涉及到数据更新的地方都有两个同名的方法重载,一个用来显示[HttpGet],一个用来数据更新[HttpPost]

  1. 在右键方法名,生成相应的View

    每个View的顶部需要添加一个声明

    @model MVCDemo.Models.SysUser

    各个view的body中具体代码:

    Create.cshtml

    <body>

<div>

<h2>Create</h2>

@using (Html.BeginForm())

{

<div>

@Html.LabelFor(model => model.UserName)

@Html.EditorFor(model => model.UserName)

</div>

<div>

@Html.LabelFor(model => model.Email)

@Html.EditorFor(model => model.Email)

</div>

<div>

@Html.LabelFor(model => model.Password)

@Html.PasswordFor(model => model.Password)

</div>

<div>

<input type="submit" value="Create" />

</div>

}

<div>@Html.ActionLink("Back to List","Index")</div>

</div>

</body>

Edit.cshtml

<body>

<div>

<h2>Edit</h2>

@using (Html.BeginForm())

{

@Html.HiddenFor(model => model.ID)

<div>

@Html.LabelFor(model => model.UserName)

@Html.EditorFor(model => model.UserName)

</div>

<div>

@Html.LabelFor(model => model.Email)

@Html.EditorFor(model => model.Email)

</div>

<div>

@Html.LabelFor(model => model.Password)

@Html.PasswordFor(model => model.Password)

</div>

<div>

<input type="submit" value="Save" />

</div>

}

<div>@Html.ActionLink("Back to List","Index")</div>

</div>

>

Delete.cshtml

<body>

<div>

<h2>Delete</h2>

<h3>Are you sure you want to delete this? </h3>

<h4>User</h4>

<dl>

<dt>@Html.DisplayNameFor(model => model.UserName)</dt>

<dd>@Html.DisplayFor(model => model.UserName)</dd>

 

<dt>@Html.DisplayNameFor(model => model.Email)</dt>

<dd>@Html.DisplayFor(model => model.Email)</dd>

</dl>

 

@using (Html.BeginForm())

{

<div>

<input type="submit" value="Delete" />

</div>

}

<div>

@Html.ActionLink("Back to List""Index")

</div>

</div>

>

NOTE

针对上面这些代码,我们提一下其中用到的HtmlHelper, 主要有这么几个:

DisplayNameFor (model=>model.xxx)à 生成纯文本,显示xxx列名

DisplayFor (model=>model.xxx)à 生成纯文本,显示xxx列的内容

LableFor à 生成一个Lable标签

EditorFor à 生成一个text类型的input

PasswordFor à 类似于EditorFor, 隐藏文本内容

ActionLink à 生成一个<a>标签

BeginForm à 生成一个表单

NOTE

HtmlHelper是可以通过View的Html属性调用的方法(@Html.xxx), 可以类比成原来WebForm的服务器端控件, 后续文章会将分成几类, 归类进行介绍,这里先简单提一下做个铺垫。这块最好的学习方法是用浏览器打开相应的页面,View page source,查看生成的相应HTML代码。

Repository Pattern

最后再补充下Repository Pattern,为下篇文章重构代码做个铺垫。

Repository Pattern是一种设计模式,这个概念大家肯定经常听到。

"企业架构模式" 上的定义:

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

具体的做法:

先定义Interface, 通过定义接口确定数据访问类的功能需求, 接着实现该接口。

以对SysUser这张表的操作为例。

先建一个文件夹 Repositories, 在文件夹中新建一个接口IsysUserRepository

我们预先定义几个功能。

namespace MVCDemo.Repositories

{

public interface ISysUserRepository

{

//查询所有用户

IQueryable<SysUser> SelectAll();

//通过用户名查询用户

SysUser SelectByName(string userName);

//添加用户

void Add(SysUser sysUser);

//删除用户

bool Delete(int id);

 

}

}

同样文件夹下新建类,继承接口,实现功能。

namespace MVCDemo.Repositories

{

public class SysUserRepository : ISysUserRepository

{

protected AccountContext db = new AccountContext();

//查询所有用户

public IQueryable<SysUser> SelectAll()

{

return db.SysUsers;

}

//通过用户名查询用户

public SysUser SelectByName(string userName)

{

return db.SysUsers.FirstOrDefault(u => u.UserName == userName);

}

//添加用户

public void Add(SysUser sysUser)

{

db.SysUsers.Add(sysUser);

db.SaveChanges();

}

//删除用户

public bool Delete(int id)

{

var delSysUser=db.SysUsers.FirstOrDefault(u => u.ID == id);

if (delSysUser != null)

{

db.SysUsers.Remove(delSysUser);

db.SaveChanges();

return true;

}

else

{

return false;

}

}

}

}

通过IsysUserRepository接口对象引用SysUserRepository类的实例来调用:

ISysUserRepository ur=new SysUserRepository();

var user=ur.xxx;

怎么样,平时听到的Repository Pattern实现起来就这么简单。

楼主提示 设计模式都来源于编程实践,只要掌握其中几个重要原则,GOF总结的设计模式都能自己推导出来,就类似于几何中的公理和定理的关系。大家工作中做个有心人,多思考,多总结。

 

总结

OK,到此为止,我们对常用的CRUD做了介绍。View, Controller之间都是通过传递Model来交互的。特别要提下下面这张图,通过navigation property实现SysUser à SysUserRole à SysRole 多表间查询。

当然,这种做法还是有局限性的,后续文章中我们会介绍如何实现类似于之前SQL查询多个表,将多个表的查询结果,例如datatable直接传到view中来显示数据。

好了,今天就到这里。


Guess you like

Origin blog.csdn.net/landeli2/article/details/79526410