问题
ASP.NET MVC makes it really easy to create editing templates for simple, flat objects. But managing CRUD for complex objects with several indirections when using something like Fluent NHibernate, is not so obvious.
Example
To illustrate my question with a simple Invoice manager, Invoice entities have a Project property:
public class Invoice
{
...
Project Project { get; set; } // where Project class has an Id and a Name
}
...which is mapped to the Projects
table via Fluent NHibernate in my InvoiceMap
:
References(x => x.Project).Inverse();
In the past, my Invoice entities would have a ProjectId
property that referenced a project in my database, which made it easier to render a select list with Project IDs, but harder to output views, e.g.:
public class Invoice
{
...
Guid ProjectID { get; set; }
}
But since I started using Fluent NHibernate, I don't want to dirty up my controller with more IDs.
InvoiceController
[HttpGet]
public ActionResult Edit(Guid id)
{
var invoice = _unitOfWork.CurrentSession.Get<Invoice>(id);
return View(invoice);
}
[HttpPost]
public ActionResult Edit(Invoice invoice)
{
/* How to deal with invoice.Project mapping here without introducing a second
action parameter, e.g. Guid projectId ? */
_unitOfWork.CurrentSession.SaveOrUpdate(invoice);
_unitOfWork.Commit();
return RedirectToAction("Details", new { id = invoice.Id });
}
The referenced Project should not be editable from my Invoice/Edit.cshtml view, but I want to be able to choose which Project the Invoice should belong to.
How should I design my views and controllers to make CRUD easy without cluttering up my controller action with reference IDs that are not flat entity fields?
回答1:
I'd suggest you create an action on your ProjectController (assuming you have one) which has a partial view which is simply a list of the projects.
e.g.
public class ProjectController : Controller
{
public ActionResult ProjectsList()
{
var projects = GetAllProjects();
return View(projects);
}
}
Project/ProjectsList.cshtml
@model IEnumerable<MyProject.Data.Models.Project>
@{ Layout = null }
<select name="project">
@foreach(var project in Model)
{
<option value="@project.Id">@project.Name</option>
}
</select>
Invoice/Edit.cshtml
<label>Title</label>
<input name="title" />
@Html.Action("ProjectsList","Project")
I would then change you Edit invoice to take an input model rather than the straight invoice and look up the project by Id in that action.
HTH
来源:https://stackoverflow.com/questions/5635588/fluent-crud-with-nhibernate-asp-net-mvc