ASP.NET MVC 编码 SQL 服务器数据库具有复合键和更新级联功能
ASP.NET MVC coding with SQL Server database with composite keys & update cascade feature
我将 EF 6 与数据库优先方法一起用于我的 ASP.NET MVC 项目,因为与 C# 和 LINQ 编码(使用 SQL 服务器 2008,Visual Studio 2015)。
我在 SQL 服务器中有 4 个 tables,每个用于:
Link, Employee, MapLinkEmp, Location
viz, link_sd1, emp_sd1, MapEmpLink_sd1, loc_sd1 respectively
A Link
与 Emp
table 存在多对多关系,为此我创建了另一个 table 引用两个 [=53] 的复合主键=]s.
为了实现软删除,我研究并最终采用了
Entity framework override save changes to soft delete entities,建议我提到的复合键
在我的项目的数据库结束时:
我在 SQL 服务器中使用复合键实现了级联功能
但是在应用程序结束时:
我无法合并 CRUD + 其他功能(包括软删除、Emp 和 Link 数据的位置分组,Emp
及其各自的位置只能更新它们的 emp 数据和 link 数据等)当我的实体中有复合键时。
SQL 级联服务器代码:
ALTER TABLE emplinkloc_sd1
ADD emid int
ALTER TABLE emplinkloc_sd1
ADD lmid int
ALTER TABLE emplinkloc_sd1
ADD isdl bit DEFAULT 0 NOT NULL
ALTER TABLE emplinkloc_sd1
ADD isde bit DEFAULT 0 NOT NULL
ALTER TABLE emplinkloc_sd1
ADD PRIMARY KEY (melid)
ALTER TABLE emplinkloc_sd1
ADD CONSTRAINT FK_ell_e_sd1
FOREIGN KEY (emid, isde) REFERENCES emp_sd1(eid, isdeleted)
ON UPDATE CASCADE;
ALTER TABLE emplinkloc_sd1
ADD CONSTRAINT FK_ell_l_sd1
FOREIGN KEY (lmid, isdl) REFERENCES link_sd1(lid, isdeleted)
ON UPDATE CASCADE;
我发现了很多技术,例如 ISoftDelete
、Interceptor
等,但我认为这些概念用于代码优先方法或 EF Core 等。此外,这些需要大量的编程,超过我目前的理解水平。
我在数据库端做的最多(如Entity framework override save changes to soft delete entities中所建议),
我应该如何使用 EF 数据库优先方法将应用程序端的功能合并到 ASP.NET MVC 的控制器和视图中以及这样的数据库模式(具有复合主键和外键)?
提前致谢!
我正在解释这项技术 - “使用存储过程和 EF6 进行 CRUD 操作的数据库优先方法” 经过大量实验后对我来说效果最好。整个过程包括数据库端的步骤,然后是应用程序端的步骤,如下面的实体描述 - 员工(在我的例子中是emp_Oct1,eid & isdeletede 作为其复合键):
数据库结束
步骤 1. 我设计的 Schema 如下(使用组合键):
步骤 2. 我在 SQL 服务器中创建了存储过程,用于为我的实体“emp_Oct1”创建、更新和软删除,如下所示:
---- For SOFT DELETION -----
CREATE PROCEDURE [dbo].[sp_deleteempt1_Oc1]
-- Add the parameters for the stored procedure here
@eid int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE emp_Oct1 SET isdeletede='1' WHERE eid=@eid
END
----- For CREATE & UPDATE -----
CREATE PROCEDURE sp_AddEditEmp_Oct1
-- Add the parameters for the stored procedure here
@eid int=0, --Named Parameter setting initial value with the parameter
@name varchar(100),
@cpf varchar(50),
@Designation varchar(50),
@Contact bigint,
@email varchar(255),
@emplocid int,
@Pwd varchar(100),
@Remarks varchar(200),
@isdeletede bit,
@elast_mod_dt datetime2,
@elast_mod_by varchar(255)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
IF(@eid>0)
BEGIN
SET NOCOUNT ON;
UPDATE emp_Oct1 SET
name=@name,cpf=@cpf,Designation=@Designation,Contact=@Contact,email=@email, emplocid=@emplocid,
Pwd=@Pwd ,Remarks=@Remarks,isdeletede=@isdeletede,elast_mod_dt=CURRENT_TIMESTAMP,elast_mod_by=@elast_mod_by
WHERE eid=@eid
END
ELSE
BEGIN
INSERT INTO emp_Oct1(name,cpf,Designation,Contact,email,emplocid,Pwd,Remarks,isdeletede,elast_mod_dt,elast_mod_by)
VALUES(@name,@cpf,@Designation,@Contact,@email,@emplocid,@Pwd,@Remarks,@isdeletede,CURRENT_TIMESTAMP,@elast_mod_by)
SELECT @eid = SCOPE_IDENTITY()
END
SELECT @eid as eid
END
GO
申请结束
步骤 1. 创建 MVC 应用程序,添加实体数据模型,如所述here
第 2 步。 我通过存储过程实现了我的 CRUD,主要思想来自这个来源CRUD Operations using Stored Procedure in Entity Framework。
步骤 3. 控制器代码
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using llpv5;
using System.Data.Entity.Validation;
namespace llpv5.Controllers
{
public class emp_Oct1Controller : Controller
{
private MyEntity db = new MyEntity();
// Emp with their respective location can see only the data of their location
public ActionResult resplocemp_linq()
{
var usercpf = System.Web.HttpContext.Current.User.Identity.Name;
var userlocid = (from e in db.emp_Oct1 where e.cpf == usercpf select e.emplocid).FirstOrDefault(); //To find location ID of the logged in user
var linkresult = (from l in db.emp_Oct1
join loc in db.loc_Oct1
on l.emplocid equals loc.locid
where l.emplocid == userlocid
&& l.isdeletede == false
&& l.name != "Admin"
select l).ToList();
if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
linkresult = (from l in db.emp_Oct1
join loc in db.loc_Oct1
on l.emplocid equals loc.locid
where l.emplocid == userlocid
&& l.isdeletede == false
&& l.name != "Admin"
select l).ToList();
}
return View(linkresult.ToList());
}
//For Admin only - Deleted items
// GET: emp_sd1
public ActionResult isdeindex()
{
var emp_sd1 = db.emp_Oct1.Include(e => e.loc_Oct1).Where(e => e.isdeletede).Where(e => e.name != "Admin");
return View(emp_sd1.ToList());
}
// GET: emp_Oct1
public ActionResult Index()
{
var emp_Oct1 = db.emp_Oct1.Include(e => e.loc_Oct1).Where(e => !e.isdeletede).Where(e => e.name != "Admin");
return View(emp_Oct1.ToList());
}
// GET: emp_Oct1/Details/5
public ActionResult Details(int? eid, bool isdeletede)
{
if (eid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
if (emp_Oct1 == null)
{
return HttpNotFound();
}
return View(emp_Oct1);
}
// GET: emp_Oct1/Create
public ActionResult Create()
{
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName");
return View();
}
// POST: emp_Oct1/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "eid,name,cpf,Designation,Contact,email,emplocid,Pwd,Remarks,isdeletede,elast_mod_dt,elast_mod_by")] emp_Oct1 emp_Oct1)
{
if (ModelState.IsValid)
{
emp_Oct1.elast_mod_by = System.Web.HttpContext.Current.User.Identity.Name;
db.emp_Oct1.Add(emp_Oct1);
db.SaveChanges();
return RedirectToAction("gindex_filter1");
}
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName", emp_Oct1.emplocid);
return View(emp_Oct1);
}
// GET: emp_Oct1/Edit/5
public ActionResult Edit(int? eid, bool isdeletede)
{
if (eid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
if (emp_Oct1 == null)
{
return HttpNotFound();
}
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName", emp_Oct1.emplocid);
return View(emp_Oct1);
}
// POST: emp_Oct1/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "eid,name,cpf,Designation,Contact,email,emplocid,Pwd,Remarks,isdeletede,elast_mod_dt,elast_mod_by")] emp_Oct1 emp_Oct1)
{
if (ModelState.IsValid)
{
emp_Oct1.elast_mod_by = System.Web.HttpContext.Current.User.Identity.Name;
db.Entry(emp_Oct1).State = EntityState.Modified;
return RedirectToAction("gindex_filter1");
}
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName", emp_Oct1.emplocid);
return View(emp_Oct1);
}
// GET: emp_Oct1/Delete/5
public ActionResult Delete(int? eid, bool isdeletede)
{
if (eid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
if (emp_Oct1 == null)
{
return HttpNotFound();
}
return View(emp_Oct1);
}
// POST: emp_Oct1/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int eid, bool isdeletede)
{
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
db.emp_Oct1.Remove(emp_Oct1);
db.SaveChanges();
return RedirectToAction("gindex_filter1");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
步骤 4. 使用 在自动生成的视图中进行适当的更改
示例查看代码如下:
@model IEnumerable<llpv5.emp_Oct1>
@{
ViewBag.Title = "Location-specific Users";
}
<center><h2>Location-specific Users</h2></center>
<table class="table table-hover table-bordered table-striped">
<tr class="table-primary">
<th>
@Html.DisplayNameFor(model => model.cpf)
</th>
<th>
@Html.DisplayNameFor(model => model.name)
</th>
<th>
@Html.DisplayNameFor(model => model.Designation)
</th>
<th>
@Html.DisplayNameFor(model => model.Contact)
</th>
<th>
@Html.DisplayNameFor(model => model.Pwd)
</th>
<th>
@Html.DisplayNameFor(model => model.loc_Oct1.LocationName)
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.cpf)
</td>
<td>
@Html.DisplayFor(modelItem => item.name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Designation)
</td>
<td>
@Html.DisplayFor(modelItem => item.Contact)
</td>
<td>
@if (User.IsInRole("Admin"))
{ @Html.DisplayFor(modelItem => item.Pwd) }
</td>
<td>
@Html.DisplayFor(modelItem => item.loc_Oct1.LocationName)
</td>
<td>
@Html.ActionLink("Details", "Details", new { eid = item.eid, isdeletede = item.isdeletede }) <text> | </text>
@Html.ActionLink("Edit", "Edit", new { eid = item.eid, isdeletede = item.isdeletede }) <text> | </text>
@Html.ActionLink("Delete", "Delete", new { eid = item.eid, isdeletede = item.isdeletede })
</td>
</tr>
}
</table>
我将 EF 6 与数据库优先方法一起用于我的 ASP.NET MVC 项目,因为与 C# 和 LINQ 编码(使用 SQL 服务器 2008,Visual Studio 2015)。
我在 SQL 服务器中有 4 个 tables,每个用于:
Link, Employee, MapLinkEmp, Location
viz, link_sd1, emp_sd1, MapEmpLink_sd1, loc_sd1 respectively
A Link
与 Emp
table 存在多对多关系,为此我创建了另一个 table 引用两个 [=53] 的复合主键=]s.
为了实现软删除,我研究并最终采用了
Entity framework override save changes to soft delete entities,建议我提到的复合键
在我的项目的数据库结束时:
我在 SQL 服务器中使用复合键实现了级联功能
但是在应用程序结束时:
我无法合并 CRUD + 其他功能(包括软删除、Emp 和 Link 数据的位置分组,Emp
及其各自的位置只能更新它们的 emp 数据和 link 数据等)当我的实体中有复合键时。
SQL 级联服务器代码:
ALTER TABLE emplinkloc_sd1
ADD emid int
ALTER TABLE emplinkloc_sd1
ADD lmid int
ALTER TABLE emplinkloc_sd1
ADD isdl bit DEFAULT 0 NOT NULL
ALTER TABLE emplinkloc_sd1
ADD isde bit DEFAULT 0 NOT NULL
ALTER TABLE emplinkloc_sd1
ADD PRIMARY KEY (melid)
ALTER TABLE emplinkloc_sd1
ADD CONSTRAINT FK_ell_e_sd1
FOREIGN KEY (emid, isde) REFERENCES emp_sd1(eid, isdeleted)
ON UPDATE CASCADE;
ALTER TABLE emplinkloc_sd1
ADD CONSTRAINT FK_ell_l_sd1
FOREIGN KEY (lmid, isdl) REFERENCES link_sd1(lid, isdeleted)
ON UPDATE CASCADE;
我发现了很多技术,例如 ISoftDelete
、Interceptor
等,但我认为这些概念用于代码优先方法或 EF Core 等。此外,这些需要大量的编程,超过我目前的理解水平。
我在数据库端做的最多(如Entity framework override save changes to soft delete entities中所建议), 我应该如何使用 EF 数据库优先方法将应用程序端的功能合并到 ASP.NET MVC 的控制器和视图中以及这样的数据库模式(具有复合主键和外键)?
提前致谢!
我正在解释这项技术 - “使用存储过程和 EF6 进行 CRUD 操作的数据库优先方法” 经过大量实验后对我来说效果最好。整个过程包括数据库端的步骤,然后是应用程序端的步骤,如下面的实体描述 - 员工(在我的例子中是emp_Oct1,eid & isdeletede 作为其复合键):
数据库结束
步骤 1. 我设计的 Schema 如下(使用组合键):
步骤 2. 我在 SQL 服务器中创建了存储过程,用于为我的实体“emp_Oct1”创建、更新和软删除,如下所示:
---- For SOFT DELETION -----
CREATE PROCEDURE [dbo].[sp_deleteempt1_Oc1]
-- Add the parameters for the stored procedure here
@eid int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE emp_Oct1 SET isdeletede='1' WHERE eid=@eid
END
----- For CREATE & UPDATE -----
CREATE PROCEDURE sp_AddEditEmp_Oct1
-- Add the parameters for the stored procedure here
@eid int=0, --Named Parameter setting initial value with the parameter
@name varchar(100),
@cpf varchar(50),
@Designation varchar(50),
@Contact bigint,
@email varchar(255),
@emplocid int,
@Pwd varchar(100),
@Remarks varchar(200),
@isdeletede bit,
@elast_mod_dt datetime2,
@elast_mod_by varchar(255)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
IF(@eid>0)
BEGIN
SET NOCOUNT ON;
UPDATE emp_Oct1 SET
name=@name,cpf=@cpf,Designation=@Designation,Contact=@Contact,email=@email, emplocid=@emplocid,
Pwd=@Pwd ,Remarks=@Remarks,isdeletede=@isdeletede,elast_mod_dt=CURRENT_TIMESTAMP,elast_mod_by=@elast_mod_by
WHERE eid=@eid
END
ELSE
BEGIN
INSERT INTO emp_Oct1(name,cpf,Designation,Contact,email,emplocid,Pwd,Remarks,isdeletede,elast_mod_dt,elast_mod_by)
VALUES(@name,@cpf,@Designation,@Contact,@email,@emplocid,@Pwd,@Remarks,@isdeletede,CURRENT_TIMESTAMP,@elast_mod_by)
SELECT @eid = SCOPE_IDENTITY()
END
SELECT @eid as eid
END
GO
申请结束
步骤 1. 创建 MVC 应用程序,添加实体数据模型,如所述here
第 2 步。 我通过存储过程实现了我的 CRUD,主要思想来自这个来源CRUD Operations using Stored Procedure in Entity Framework。
步骤 3. 控制器代码
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using llpv5;
using System.Data.Entity.Validation;
namespace llpv5.Controllers
{
public class emp_Oct1Controller : Controller
{
private MyEntity db = new MyEntity();
// Emp with their respective location can see only the data of their location
public ActionResult resplocemp_linq()
{
var usercpf = System.Web.HttpContext.Current.User.Identity.Name;
var userlocid = (from e in db.emp_Oct1 where e.cpf == usercpf select e.emplocid).FirstOrDefault(); //To find location ID of the logged in user
var linkresult = (from l in db.emp_Oct1
join loc in db.loc_Oct1
on l.emplocid equals loc.locid
where l.emplocid == userlocid
&& l.isdeletede == false
&& l.name != "Admin"
select l).ToList();
if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
linkresult = (from l in db.emp_Oct1
join loc in db.loc_Oct1
on l.emplocid equals loc.locid
where l.emplocid == userlocid
&& l.isdeletede == false
&& l.name != "Admin"
select l).ToList();
}
return View(linkresult.ToList());
}
//For Admin only - Deleted items
// GET: emp_sd1
public ActionResult isdeindex()
{
var emp_sd1 = db.emp_Oct1.Include(e => e.loc_Oct1).Where(e => e.isdeletede).Where(e => e.name != "Admin");
return View(emp_sd1.ToList());
}
// GET: emp_Oct1
public ActionResult Index()
{
var emp_Oct1 = db.emp_Oct1.Include(e => e.loc_Oct1).Where(e => !e.isdeletede).Where(e => e.name != "Admin");
return View(emp_Oct1.ToList());
}
// GET: emp_Oct1/Details/5
public ActionResult Details(int? eid, bool isdeletede)
{
if (eid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
if (emp_Oct1 == null)
{
return HttpNotFound();
}
return View(emp_Oct1);
}
// GET: emp_Oct1/Create
public ActionResult Create()
{
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName");
return View();
}
// POST: emp_Oct1/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "eid,name,cpf,Designation,Contact,email,emplocid,Pwd,Remarks,isdeletede,elast_mod_dt,elast_mod_by")] emp_Oct1 emp_Oct1)
{
if (ModelState.IsValid)
{
emp_Oct1.elast_mod_by = System.Web.HttpContext.Current.User.Identity.Name;
db.emp_Oct1.Add(emp_Oct1);
db.SaveChanges();
return RedirectToAction("gindex_filter1");
}
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName", emp_Oct1.emplocid);
return View(emp_Oct1);
}
// GET: emp_Oct1/Edit/5
public ActionResult Edit(int? eid, bool isdeletede)
{
if (eid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
if (emp_Oct1 == null)
{
return HttpNotFound();
}
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName", emp_Oct1.emplocid);
return View(emp_Oct1);
}
// POST: emp_Oct1/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "eid,name,cpf,Designation,Contact,email,emplocid,Pwd,Remarks,isdeletede,elast_mod_dt,elast_mod_by")] emp_Oct1 emp_Oct1)
{
if (ModelState.IsValid)
{
emp_Oct1.elast_mod_by = System.Web.HttpContext.Current.User.Identity.Name;
db.Entry(emp_Oct1).State = EntityState.Modified;
return RedirectToAction("gindex_filter1");
}
ViewBag.emplocid = new SelectList(db.loc_Oct1, "locid", "LocationName", emp_Oct1.emplocid);
return View(emp_Oct1);
}
// GET: emp_Oct1/Delete/5
public ActionResult Delete(int? eid, bool isdeletede)
{
if (eid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
if (emp_Oct1 == null)
{
return HttpNotFound();
}
return View(emp_Oct1);
}
// POST: emp_Oct1/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int eid, bool isdeletede)
{
emp_Oct1 emp_Oct1 = db.emp_Oct1.Find(eid, isdeletede);
db.emp_Oct1.Remove(emp_Oct1);
db.SaveChanges();
return RedirectToAction("gindex_filter1");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
步骤 4. 使用
@model IEnumerable<llpv5.emp_Oct1>
@{
ViewBag.Title = "Location-specific Users";
}
<center><h2>Location-specific Users</h2></center>
<table class="table table-hover table-bordered table-striped">
<tr class="table-primary">
<th>
@Html.DisplayNameFor(model => model.cpf)
</th>
<th>
@Html.DisplayNameFor(model => model.name)
</th>
<th>
@Html.DisplayNameFor(model => model.Designation)
</th>
<th>
@Html.DisplayNameFor(model => model.Contact)
</th>
<th>
@Html.DisplayNameFor(model => model.Pwd)
</th>
<th>
@Html.DisplayNameFor(model => model.loc_Oct1.LocationName)
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.cpf)
</td>
<td>
@Html.DisplayFor(modelItem => item.name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Designation)
</td>
<td>
@Html.DisplayFor(modelItem => item.Contact)
</td>
<td>
@if (User.IsInRole("Admin"))
{ @Html.DisplayFor(modelItem => item.Pwd) }
</td>
<td>
@Html.DisplayFor(modelItem => item.loc_Oct1.LocationName)
</td>
<td>
@Html.ActionLink("Details", "Details", new { eid = item.eid, isdeletede = item.isdeletede }) <text> | </text>
@Html.ActionLink("Edit", "Edit", new { eid = item.eid, isdeletede = item.isdeletede }) <text> | </text>
@Html.ActionLink("Delete", "Delete", new { eid = item.eid, isdeletede = item.isdeletede })
</td>
</tr>
}
</table>