我需要一些关于在何处运行数据计算的建议。
我有一个viewmodel,其中包含我计算所需的所有字段,并为计算之一创建了以下字段:
public class CommissionVM
{
public int? LoanAmountLock { get; set; } // from loan table
public decimal BranchRev { get; set; } // from revenue table
public decimal BranchProcessFee { get; set; } // from revenue table
public decimal BranchGrossTotal
{
get
{
return Convert.ToDecimal(LoanAmountLock * (BranchRev/ 100) + BranchProcessFee);
}
}
}
我试图在我的视图中使用Model.BranchGrossTotal,但它返回0.我认为我有一个操作顺序问题。值LoanAmountLock
,BranchRev
和BranchProcessFee
将作为查询结果返回:
public ActionResult Reconcile(int? id, string RevenueLoanType)
{
var model = new CommissionVM()
{
Loan = db.Loan.FirstOrDefault(a => a.id == id ),
BranchRevenues = db.BranchRevenues.FirstOrDefault(a => a.RevenueLoanType == RevenueLoanType),
};
return View(model);
}
我最初能够通过在查询中填充viewmodel后在控制器中完成所有数学计算来实现这些计算,但是会有大约10个计算,根据我的理解,我不应该这样做用业务逻辑弄乱我的控制器。
最佳解决方案是什么?我是否需要为计算创建另一个类?如果是这样,我如何用我的数据填充该类并在我的控制器中使用它?
编辑:我不确定如何设置业务类并在控制器中使用它们。任何人都可以指向我的教程方向吗?
答案 0 :(得分:6)
您不应在控制器或视图模型中进行计算。您应该在业务层中执行此操作。想想View Models是非常简单的类,包含要向用户显示的数据,就是它。
关于计算,您应将其中一个术语转换为十进制,而不是计算结果。如果你除以整数,你会得到一个整数。
例如,您可以创建一个类并将其命名为CommissionService。该类应调用您的数据层来获取数据,进行任何额外的计算并将数据(可能是DTO)返回给控制器。控制器应该基于DTO创建视图模型并将它们发送到视图。
阅读这些文章:
1)https://msdn.microsoft.com/en-us/library/hh404093.aspx
3)http://blog.diatomenterprises.com/asp-net-mvc-business-logic-as-a-separate-layer/
4)http://sampathloku.blogspot.com.ar/2012/10/how-to-use-viewmodel-with-aspnet-mvc.html
答案 1 :(得分:2)
首先,您在控制器上分配给CommissionVM的属性与模型上声明的属性不匹配。如果模型上只有LoanAmountLock和BranchRevs,则可以分配Loan和BranchRevenues。 请注意,Loan属性本身就是一个对象,并且必须从该对象(Loan.LoanAmountLock)中检索LoanAmountLock。 BranchRevenues对象也是如此。您应该根据需要将BranchRevs分配给BranchRevenues对象的相应属性。如果你不这样做,那么值将默认为0,当尝试计算BranchGrossTotal时,它显然是0。
假设您正确填充模型属性,另一个原因是FirstOrDefault方法因为没有这样的实体而呈现空值。这将导致BranchGrossTotal为0。
你是对的,你既不需要计算也不需要使用db访问来控制你的控制器。我将创建一个商业类ComissionBusiness并在控制器的顶部实例化它。这个类有一个执行所有计算的方法。您应该将Reconcile方法移动到新的业务类方法,并在协调操作上调用它。有点像(借口缺乏语法)
public MyController : Controller {
public ComissionBusiness comissionBusiness;
public MyController(){
comissionBusiness = new ComissionBusiness();
}
public ActionResult Reconcile(int? id, string RevenueLoanType)
{
var model = comissionBusiness.Reconcile(id, revenueLoanType);
return View(model);
}
}
答案 2 :(得分:2)
我不喜欢在我的视图模型上进行计算 - 您无法在其他地方轻松地重复使用计算,并且测试和调试更加困难。创建单独的类来执行业务逻辑。
您的业务逻辑类可以返回视图模型,也可以返回用于填充这些模型的值。权衡是易用性和可重用性。
我通常倾向于返回值而不是大对象,因此我的服务更可重用。
<强>控制器强>
public class BranchController : Controller
{
private IBusinessService service;
public BranchController()
{
this.service = new BusinessService(db);
}
public ActionResult Reconcile(int? id, string RevenueLoanType)
{
var model = new CommissionVM
{
BranchGrossTotal = this.service.GetBranchGrossTotal(id, RevenueLoanType),
...
};
return View(model);
}
}
<强>服务强>
你可以制作任意数量的这些,你的控制器会根据需要使用它们。如果您需要查询,则应传递DbContext实例,否则您可能在不同的上下文中遇到相关实体的问题。
public interface IBusinessService
{
decimal GetBranchGrossTotal(int id, string revenueLoanType);
}
public class BusinessService : IBusinessService
{
private DbContext db;
public BusinessService(DbContext db)
{
this.db = db;
}
public decimal GetBranchGrossTotal(int id, string revenueLoanType)
{
var branch = db.Branch.First(b => b.Id == id);
// do stuff
return total;
}
}
如果您愿意,可以在GetBranchGrossTotal()
中完全填充并返回视图模型。