ASP.NET MVC 与抽象层的实体框架
本文关键字:实体 框架 抽象 NET MVC ASP | 更新日期: 2023-09-27 17:56:09
我正在尝试在PluralSight上扩展一个项目。 在这个项目中,我在数据库Employees
和Departments
中有两个表,在 Departments
和 Employees
之间有 1 对多。 为了防止控制器知道我的DbContext
我使用以下接口:
public interface IDepartmentDataSource
{
IQueryable<Employee> Employees { get; }
IQueryable<Department> Departments { get; }
}
数据库上下文:
public class DepartmentDb : DbContext, IDepartmentDataSource
{
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
public DepartmentDb() :base("DefaultConnection") { }
IQueryable<Employee> IDepartmentDataSource.Employees
{
get { return Employees; }
}
IQueryable<Department> IDepartmentDataSource.Departments
{
get { return Departments; }
}
//this is the part that's wrong I believe
public void AddDepartment(Department dept)
{
this.Departments.Add(dept);
this.SaveChanges();
}
}
控制器
public class DepartmentController : Controller
{
//private readonly IDepartmentDataSource _db = new DepartmentDb();
DepartmentDb _db = new DepartmentDb();
public DepartmentController(DepartmentDb db)
{
_db = db;
}
public ActionResult Detail(int id)
{
var model = _db.Departments.Single(x => x.Id == id);
return View(model);
}
[HttpGet]
public ActionResult Create()
{
return View(new Department());
}
[HttpPost]
public ActionResult Create(Department department)
{
_db.AddDepartment(department);
_db.SaveChanges();
return View(department);
}
}
视图:
@model eManager.Domain.Department
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm("Create","Department"))
{
<fieldset>
<legend>City</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Id)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Id)
@Html.ValidationMessageFor(model => model.Id)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
这似乎是使用存储库模式(我无法实现端到端)的好地方。 但是当我尝试提交表单时,我收到一条错误消息,指出未传递参数。 为什么 MVC 不挑选已发布的表单值作为参数?
你不会给自己买任何东西来做这样的抽象。用于DbContext
的 API 会向控制器操作公开,即使实际的 DbContext
类不是。无论如何,更改为另一个 ORM、WCF 服务等将从根本上影响您的操作代码。
如果你想要一个真正的抽象,创建一个存储库或服务类,它将在其构造函数中获取DbContext
的实例,然后通过自定义 API 公开DbSet
的结果(即不要只返回DbSet
或可查询)。
为了将这些不同的存储库或服务连接在一起,以便您最终不会得到上下文的多个实例,传统上,您需要创建类作为工作单元,由存储库或服务组成。但是,通过这样做,您基本上只是创建了一个俄罗斯套娃,其中您在工作单元内的存储库中有一个工作单元。我发现这里更好的方法是使用依赖项注入框架,为您的上下文使用每个请求范围生存期管理器。这样,相同的上下文实例就会馈送到 DI 容器实例化的每个存储库或服务中。
同样,我会引导您更多地使用服务而不是存储库。它主要是语义,但服务应该有更具体的方法(blogPostService.GetMostRecentPublishedPosts()
vs. blogPostRepo.GetAll()
)并返回完全烘焙的数据(无需进一步查询),而存储库通常返回一组未成形的数据,您需要进一步过滤、排序等。
尝试传入"FormCollection",看看会发生什么
[HttpPost]
public ActionResult Create(FormCollection form)
{
// new up a viewmodel here or something
var model = new Department();
// database stuff
}