Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NETMVC:这种业务逻辑应该去哪里?_C#_Asp.net Mvc_Oop - Fatal编程技术网

C# ASP.NETMVC:这种业务逻辑应该去哪里?

C# ASP.NETMVC:这种业务逻辑应该去哪里?,c#,asp.net-mvc,oop,C#,Asp.net Mvc,Oop,我正在开发我的第一个真正的MVC应用程序,并尝试遵循一般的OOP最佳实践。我正在将控制器中的一些简单业务逻辑重构到域模型中。我最近读了一些书,似乎很清楚我应该把逻辑放在域模型实体类的某个地方,以避免“贫血的域模型”反模式 该应用程序将允许人们购买停车位租赁。费率取决于现场的长度以及客户是否为商业园区的成员 因此,我的域模型中有如下实体类(简化): 编辑:只是为了澄清leasequeote不是一个实体类,因为它只是用于向透视客户显示成本明细,并且不会保存在任何地方 public class Lea

我正在开发我的第一个真正的MVC应用程序,并尝试遵循一般的OOP最佳实践。我正在将控制器中的一些简单业务逻辑重构到域模型中。我最近读了一些书,似乎很清楚我应该把逻辑放在域模型实体类的某个地方,以避免“贫血的域模型”反模式

该应用程序将允许人们购买停车位租赁。费率取决于现场的长度以及客户是否为商业园区的成员

因此,我的域模型中有如下实体类(简化):

编辑:只是为了澄清leasequeote不是一个实体类,因为它只是用于向透视客户显示成本明细,并且不会保存在任何地方

public class LeaseQuote
{
    int SubTotal { get; set; }
    int Discount { get; set; }
    int Total { get; set; }
}
现在,作为应用程序的一项功能,我需要能够为不同的客户和停车位组合生成报价。报价通常在实际创建租赁的上下文之外访问,例如当客户打电话询问价格时

那么最好的方法是什么呢?在控制器内实例化一个新的ParkingSpaceLease对象,只是为了对其调用GetQuote方法,这有意义吗

var lease = new ParkingSpaceLease();
var quote = lease.GetQuote(length: 168, isMember: true);
return Json(quote);
或者leasequeote类应该有这个方法吗

var leaseQuote = new LeaseQuote();
var quote = leaseQuote.GetQuote(length: 168, isMember: true);
return Json(quote);
把逻辑放在实际的ParkingSpaceLease类中感觉很奇怪。我想当我知道除了访问GetQuote方法之外,我实际上不打算对它做任何事情时,创建一个新的lease对象感觉有点“沉重”,它看起来有点像一个单独的服务


那么GetQuote方法应该放在哪里,为什么要放在那里呢?

只要在ParkingSpaceLease中将GetQuote设置为静态方法。

我认为您的对象模型可能有点歪斜,这会导致您担心租约是获取报价的错误位置。在我看来,租赁将完全由正在租赁的停车位组成,并且仅与购买租赁的客户相关。IOW:

public class ParkingSpace
{
    int ID { get; set; }
    int Length { get; set; }
    IEnumerable<ParkingSpaceLease> Leases { get; set; }
    LeaseQuote GetQuote(Customer customer/*, other relevant parameters */) { ... }
}

public class ParkingSpaceLease
{
    int ID { get; set; }
    DateTime OpenDate { get; set; }
    DateTime CloseDate { get; set; }
    Customer Customer { get; set; }
}

public class LeaseQuote
{
    //Properties
    ParkingSpaceLease GetLease();
}
公共级停车空间
{
int ID{get;set;}
整数长度{get;set;}
IEnumerable租约{get;set;}
LeaseQuote GetQuote(Customer/*,其他相关参数*/){…}
}
公共级停车场租赁
{
int ID{get;set;}
DateTime OpenDate{get;set;}
DateTime CloseDate{get;set;}
客户{get;set;}
}
公共类租赁
{
//性质
ParkingSpaceLease GetLease();
}

编辑我错过了关于LeaseQuote是一个独立类的部分。

听起来你的LeaseQuote似乎不是一个实体,更像是一个业务级别的类。我的意思是,你没有把它存储在数据库的任何地方,是吗?它不是另一个数据对象的一部分

当我看到这个

现在,作为应用程序的一项功能,我需要能够为不同的客户和停车位组合生成报价。报价通常在实际创建租赁的上下文之外访问,例如当客户打电话询问价格时

我想到这样的方法签名

public LeaseQuote GetQuote(Customer customer, ParkingSpace parkingSpace, int length)
但考虑到这一点,我可能还想在
停车空间
实体中存储有关停车位成本的信息,并在
客户
实体中存储(如果适用)客户折扣的信息

这些东西会去哪里?在访问实体并充当控制器提供者的模型类(业务模型,而不是LINQ或实体模型)中

现在我知道你的模型没有完全按照我写的那样使用。这可能只是个人偏见。但是当我想到数据模型和数据实体时,它们不应该有任何附加方法,而不是从数据库返回的方法。它们应该只表示数据库中显示的未更改的数据。如果您对数据进行操作,则该数据属于数据实体之上的一层

更新:

我对您的示例感到好奇的是,为什么要传递完整的实体对象(客户和停车位)而不是执行计算所需的属性

这取决于你的代码标准。如果消费代码操纵实体,则暴露实体本身可能是危险的。我更喜欢传递实体,主要是因为我已经习惯了。但我也很小心,不要在进入的过程中操纵实体。我认为方法签名反映了GetQuote方法的重点;它与客户和停车位有关

我还可以这样做,如果以后有更多的字段进入实体,从而影响GetQuote方法,那么方法签名就不必更改。在这种情况下,只有GetQuote的实现需要更改


简短回答:首选项。

你说得对,leasekote不是一个实体。我应该说清楚的。有关购买、折扣信贷和付款的信息都将反映在租赁实际创建后发生的交易中,因此租赁通知的目的实际上只是为潜在客户显示细分。从您的示例中我很好奇的是,为什么要传递完整的实体对象(Customer和Parking Space)而不是执行计算所需的属性?图:)是的,将计算放在另一个模型类中(可能是LeaseManager,它还可以有添加新租约、删除租约、更新租约等方法。)或者,如果您认为它不会在其他任何地方使用,请将其放置在控制器中。您能否回答我关于接受实体对象而不是属性值的方法签名的问题?在您发布答复之前,我已经在问题中进行了编辑!这是“不必担心”的回答?
public LeaseQuote GetQuote(Customer customer, ParkingSpace parkingSpace, int length)