agg*_*gie 9 c# asp.net-mvc entity-framework viewmodel
谁负责填充ASP MVC 5架构(C#,EF)中的值,例如,如果我们有 PurchaseRecordsViewModel , PurchaseRecords Domain Model , PurchaseController
填充数据的代码(时间,成本等)是否为viewmodel,就在它自己的viewmodel中进入PurchaseRecordsViewModel?
或者,代码是否在Action的Action方法中 PurchaseController
Tom*_*mmy 12
视图模型通常只是属性的愚蠢集合.填充视图模型通常位于服务层内部,如果没有,则采用操作方法.
以这种方式考虑角色.
通常问的另一个问题是为什么我不能将域模型用于视图?您可以,但通常会遇到类似这样的问题,需要来自多个域模型的数据,不需要域模型中的所有属性,最后,您现在必须担心在您的域模型上更新属性不打算.
扩展Tommy的答案,这里有一些代码与他的描述一致.
//Controller
public ActionResult Index()
{
List<OrderViewModel>() model = new List<OrderViewModel>();
model = new ServiceClass().GetOrders();
return View(model);
}
//here is your Service Class, this layer transfers the Domain Model into your ViewModel
public List<OrderViewModel> GetOrders()
{
List<OrderDomain> model = new List<OrderDomain>();
model = new DataAccess().GetOrders();
List<OrderViewModel> viewModel = new List<OrderViewModel>();
foreach (var order in model)
{
OrderViewModel vm = new OrderViewModel();
vm.OrderId = order.OrderId;
vm.OrderName = order.OrderName;
viewModel.Add(vm);
}
return viewModel;
}
//some DataAccess class, this class is used for database access
Public List<OrderDomain> GetOrders()
{
List<OrderDomain> model = new List<OrderDomain>();
using (var context = new MyEntities())
{
model = (from x in context.Order
select new OrderDomain
{
OrderId = x.OrderId,
OrderName = x.OrderName
}).ToList();
}
return model;
}
Run Code Online (Sandbox Code Playgroud)
编辑:这似乎是一个温和的流行答案,所以我想提一下我不再遵循这种模式.相反,我一直在使用mediatr和垂直切片架构.
理想情况下,PurchaseRecordViewModel应该通过获取来填充自己PurchaseRecordsDomainModel.它应该包含属性的简单映射,并且可能包含您将在视图中使用的输出的某些格式.
PurchaseRecordsViewModel
public class PurchaseRecordsViewModel
{
public IEnumerable<PurchaseRecordViewModel> PurchaseRecords {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
PurchaseRecordViewModel
public class PurchaseRecordViewModel
{
public DateTime Date {get;set;}
public decimal Cost {get;set;}
// .... some other properties
public PurchaseRecordsViewModel(PurchaseRecordsDomainModel domainModel)
{
Date = domainModel.Date;
Cost = domainModel.Cost;
// .... some other property mappings
}
}
Run Code Online (Sandbox Code Playgroud)
你的action方法上PurchaseController应该做的,是策划让你的过程中PurchaseRecordsDomainModel,创造PurchaseRecordsViewModel从PurchaseRecordsDomainModel并将它传递给了View.Action方法本身不应包含任何处理从数据库连接和检索数据的代码(在您的情况下查询EF上下文)或任何业务逻辑.您应该尝试使用松散耦合的模块,通过相互通信abstractions,这样您将确保您的应用程序是maintainable,extensible和testable.
此外,尝试在系统的各个层之间绘制清晰的分隔.例如,拥有EF entitiesas 不是一个好主意Domain Model Entites.您不希望您business logic layer依赖data access layer,以这种方式考虑,如果在将来的某个时间点,您正在远离EF并使用其他ORM甚至其他技术来存储和查询数据.你不想business logic layer因为改变你的想法而改变data access layer.所以在你的情况下从单词到代码.
考虑到你已经有你view和view model我将创建PurchaseRecordsService类domain layer(请注意:根据你的情况,你可能不会使用Repositories,但其它一些技术,这个例子主要是为了说明我的观点)
public class PurchaseRecordsService
{
private readonly IPurchaseRecordsRepository _purchaseRecordsRepository;
public PurchaseRecordsService(IPurchaseRecordsRepository purchaseRecordsRepository)
{
if(purchaseRecordsRepository == null)
{
throw new ArgumentNullException("purchaseRecordsRepository");
}
_purchaseRecordsRepository = purchaseRecordsRepository;
}
public IEnumerable<PurchaseRecordsDomainModel> GetPurchaseRecords()
{
// trivial case, real code can be more complex
return _purchaseRecordsRepository.GetPurchaseRecords();
}
}
Run Code Online (Sandbox Code Playgroud)
然后在你的domain layer,你可以定义IPurchaseRecordsRepository
public interface IPurchaseRecordsRepository
{
IEnumerable<PurchaseRecordsDomainModel > GetPurchaseRecords();
}
Run Code Online (Sandbox Code Playgroud)
我们的想法是,我们PurchaseRecordsService需要一种与数据库进行通信的方式,因此无论谁使用它,都必须提供实现IPurchaseRecordsRepository.下一步是移动到我们的data access layer创建实现类IPurchaseRecordsRepository.
public class EfPurchaseRecordsRepository: IPurchaseRecordsRepository
{
private readonly EfObjectContext _objectContext;
public EfPurchaseRecordsRepository(string connectionString)
{
_objectContext = new EfObjectContext(connectionString);
}
public IEnumerable<PurchaseRecordsDomainModel > GetPurchaseRecords()
{
var purchaseRecords = (from p in _objectContext.PurchaseRecords
....
select p).AsEnumerable();
return purchaseRecords .Select(p => p.ConvertToDomainPurchaseRecord());
}
}
Run Code Online (Sandbox Code Playgroud)
最后一块 - 我们需要定义我们Action的内容PurchaseController
public class PurchaseController: Controller
{
private readonly IPurchaseRecordsRepository _repository;
public PurchaseController(IPurchaseRecordsRepository repository)
{
if(repository == null)
{
throw new ArgumentNullException("repository");
}
_repository = repository;
}
public ActionResult Index()
{
var purchaseRecordsService = new PurchaseRecordsService(_repository);
var purchaseRecordsViewModel = new PurchaseRecordsViewModel();
var purchaseRecords = purchaseRecordsService.GetPurchaseRecords();
foreach(var purchaseRecord in purchaseRecords)
{
var purchaseRecordViewModel = new PurchaseRecordViewModel(purchaseRecord);
purchaseRecordsViewModel.PurchaseRecords.Add(purchaseRecordViewModel);
}
return View(purchaseRecordsViewModel);
}
}
Run Code Online (Sandbox Code Playgroud)
回顾一下,我们所拥有的是松散耦合的代码,我们Presentation和Data AccessLayers彼此不了解,并且它们仅依赖于Domain层.如果需要,可以替换MVC前端WPF,例如,从EF另一种技术转移,您的代码是可测试的.
| 归档时间: |
|
| 查看次数: |
9075 次 |
| 最近记录: |