我已经创建了一个POCO模型类和一个处理持久性的存储库类.因为POCO不能访问存储库,所以存储库中有很多业务逻辑任务,这似乎不太对.根据我所读到的内容,看起来我需要一个位于UI使用者和存储库层之间的服务层.我不确定的是它到底是怎么工作的…
除了服务层,还应该有一个单独的业务逻辑层,还是服务层的角色?
每个存储库应该有一个服务吗?
服务层是UI实例化模型对象的唯一方式,还是存储库向服务提供新的模型实例?
我是否要将我的参数、模型和其他验证放在服务层中,以便在更新之前执行判断之类的操作,以确保输入有效以及数据库中存在要更新的项?
模型、存储库和UI是否都可以调用服务层,还是只供UI使用?
服务层应该是所有静态方法吗?
从UI调用服务层的典型方式是什么?
应该对模型和服务层进行哪些验证?
以下是我现有图层的一些示例代码:
public class GiftCertificateModel
{
public int GiftCerticiateId {get;set;}
public string Code {get;set;}
public decimal Amount {get;set;}
public DateTime ExpirationDate {get;set;}
public bool IsValidCode(){}
}
public class GiftCertificateRepository
{
//only way to access database
public GiftCertificateModel GetById(int GiftCertificateId) { }
public List<GiftCertificateModel> GetMany() { }
public void Save(GiftCertificateModel gc) { }
public string GetNewUniqueCode() { //code has to be checked in db }
public GiftCertificateModel CreateNew()
{
GiftCertificateModel gc = new GiftCertificateModel();
gc.Code = GetNewUniqueCode();
return gc;
}
}
UPDATE:
UPDATE:非常感谢@Lester的精彩解释.我现在明白了,我需要为我的每个存储库添加一个服务层.该层将是UI或其他服务与存储库通信的唯一方式,并将包含任何不适合域对象的验证(例如,需要调用repo的验证)
public class GiftCertificateService()
{
public void Redeem(string code, decimal amount)
{
GiftCertificate gc = new GiftCertificate();
if (!gc.IsValidCode(code))
{
throw new ArgumentException("Invalid code");
}
if (amount <= 0 || GetRemainingBalance(code) < amount)
{
throw new ArgumentException("Invalid amount");
}
GiftCertificateRepository gcRepo = new GiftCertificateRepository();
gcRepo.Redeem(code, amount);
}
public decimal GetRemainingBalance(string code)
{
GiftCertificate gc = new GiftCertificate();
if (!gc.IsValidCode(code))
{
throw new ArgumentException("Invalid code");
}
GiftCertificateRepository gcRepo = new GiftCertificateRepository();
gcRepo.GetRemainingBalance(code);
}
public SaveNewGC(GiftCertificate gc)
{
//validates the gc and calls the repo save method
//updates the objects new db ID
}
}
Questions
我是否向服务中添加了与我的模型相同(可能更多)的属性(金额、代码等),还是只提供接受GiftCertificate对象和直接参数的方法?
我是在调用服务构造函数时创建GiftCertificate实体的默认实例,还是根据需要创建新实例(例如,对于服务中需要调用实体中验证方法的验证方法?还有,关于创建默认存储库实例的相同问题...?
我知道我通过服务公开了repo的功能,我是否也公开了来自实体的方法(例如,IsValidCode等)?
UI可以直接创建一个新的GiftCertificate对象,而不需要通过服务(例如,从实体调用参数验证方法).若否,如何执行?
在UI层上,当我想要创建一个新的礼品证书时,我是直接从UI层调用模型/服务验证(如IsValidExpirationDate等),还是先将对象水合,然后将其传递给验证,然后将某种验证摘要返回到UI?
另外,如果我想从UI层进行兑换,是否首先从UI调用模型/服务验证方法以提供用户反馈,然后调用将在内部再次运行相同判断的redeem方法?
Example for calling service to do a Redeem operation from UI:个
string redeemCode = RedeemCodeTextBox.Text;
GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate(); //do this to call validation methods (should be through service somehow?)
if (!gc.IsValid(redeemCode))
{
//give error back to user
}
if (gcService.GetRemainingBalance(redeemCode) < amount)
{
//give error back to user
}
//if no errors
gcService.Redeem(code,amount);
Example for creating a new Gift certificate from UI:
GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate();
if (!gc.IsValidExpDate(inputExpDate))
{
//give error to user..
}
//if no errors...
gc.Code = gcService.GetNewCode();
gc.Amount = 10M;
gc.ExpirationDate = inputExpDate;
gcService.SaveNewGC(gc);
//method updates the gc with the new id...
GCs的创建方式以及验证如何在实体/服务之间分离,让人感觉有些不对劲.用户/消费者不必关心在哪个地方进行了哪些验证...劝告