gpt4 book ai didi

c# - 服务层如何适合我的存储库实现?

转载 作者:IT王子 更新时间:2023-10-29 03:49:04 28 4
gpt4 key购买 nike

我创建了一个 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;
}
}

更新:
我目前正在使用 Web 表单和经典的 ADO.NET。我希望最终转向 MVC 和 EF4。

更新:非常感谢@Lester 的精彩解释。我现在明白我需要为我的每个存储库添加一个服务层。该层将是 UI 或其他服务与存储库通信的唯一方式,并将包含任何不适合域对象的验证(例如 - 需要调用存储库的验证)
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
}

}

问题
  • 我是否向服务添加了与我的模型相同(并且可能更多)的属性(金额、代码等),还是仅提供接受 GiftCertificate 对象和直接参数的方法?
  • 我是在调用 Service 构造函数时创建 GiftCertificate 实体的默认实例,还是根据需要创建新实例(例如 - 对于需要调用实体中的验证方法的服务中的验证方法?另外,关于创建默认值的相同问题存储库实例...?
  • 我知道我通过服务公开了 repo 的功能,我是否也公开了实体的方法(例如 - IsValidCode 等)?
  • UI 可以直接创建一个新的 GiftCertificate 对象而不通过服务(例如 - 从实体调用参数验证方法)。如果没有,如何执行?
  • 在 UI 层,当我想创建一个新的礼券时,我是直接从 UI 层调用模型/服务验证(如 IsValidExpirationDate 等)还是先对对象进行水合,然后将其传入以进行验证和然后将某种验证摘要返回给用户界面?

  • 另外,如果我想从 UI 层进行 Redeem,我是否首先从 UI 调用模型/服务验证方法来提供用户反馈,然后调用将在内部再次运行相同检查的 Redeem 方法?

    从 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);

    从 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...

    关于 GC 的创建方式以及实体/服务之间的验证如何分离,感觉有些不对劲。用户/消费者不应该关心哪些验证在哪个地方......建议?

    最佳答案

    看看S#arp Architeture .它就像一个用于构建 ASP.NET MVC 应用程序的最佳实践架构框架。一般的架构模式是每个实体有 1 个存储库,仅负责数据访问,每个存储库有 1 个服务,仅负责业务逻辑以及 Controller 和服务之间的通信。

    根据 S#arp 架构回答您的问题:

    除了服务层,还应该有单独的业务逻辑层,还是服务层的作用?

    模型应该负责字段级别的验证(例如使用必需的字段属性),而 Controller 可以在保存之前验证数据(例如,在保存之前检查状态)。

    每个存储库应该有一个服务层吗?

    是的 - 每个存储库应该有一个服务(不是每个存储库 1 个服务层,但我猜你是这个意思)。

    服务层是 UI 可以实例化模型对象的唯一方式,还是存储库向服务提供新的模型实例?

    存储库和服务可以根据需要返回单个实体、实体集合或数据传输对象 (DTO)。 Controller 会将这些值传递给模型中的静态构造函数方法,该方法将返回模型的实例。

    ex 使用 DTO:

    GiftCertificateModel.CreateGiftCertificate(int GiftCerticiateId, string Code, decimal Amount, DateTime ExpirationDate)

    我是否将我的参数、模型和其他验证放在服务层中,以执行诸如检查以确保输入有效以及更新前数据库中存在要更新的项目之类的操作?

    模型验证字段级值,例如。通过检查必填字段、年龄或日期范围等来确保输入有效。服务应该进行任何需要检查模型值之外的验证。检查礼券尚未兑换,检查礼券所在商店的属性)。

    模型、存储库和 UI 是否都可以调用服务层,还是只是让 UI 消费?

    Controller 和其他服务应该是唯一调用服务层的服务。服务应该是唯一调用存储库的方法。

    服务层应该都是静态方法吗?

    它们可以,但如果不是,则更容易维护和扩展。如果每个实体/子类有 1 个服务,则更容易更改实体和添加/删除子类。

    从 UI 调用服务层的典型方法是什么?

    Controller 调用服务层的一些示例:
    giftCertificateService.GetEntity(giftCertificateId); (which in turn is just a call to the giftCertificateRepository.GetEntity(giftCertificateId)

    giftCertificateService.Redeem(giftCertificate);

    模型与服务层应该进行哪些验证?

    上面已经回答了。

    更新

    由于您使用的是 WebForms,因此掌握一些概念可能有点困难,但我提到的所有内容都适用,因为我所描述的是通用 MVC 范例。用于数据访问的 ADO.NET 无关紧要,因为数据访问是通过存储库分离的。

    我是否向服务添加了与我的模型相同(可能更多)的属性(金额、代码等),还是仅提供接受 GiftCertificate 对象和直接参数的方法?

    您需要按照服务名称的含义来查看服务 - Controller 可以调用的操作。您不需要模型中定义的属性,因为它们已经在模型中可用。

    我是在调用 Service 构造函数时创建 GiftCertificate 实体的默认实例,还是根据需要创建新实例(例如 - 对于需要调用实体中的验证方法的服务中的验证方法?另外,关于创建默认值的相同问题存储库实例...?

    Controller 和服务应该分别具有服务和存储库的私有(private)字段。您不应该为每个操作/方法进行实例化。

    我知道我通过服务公开了 repo 的功能,我是否也公开了实体的方法(例如 - IsValidCode 等)?

    不太清楚你在这里的意思。如果服务返回实体,则实体上的那些方法已经公开。如果他们返回 DTO,则意味着您只对某些信息感兴趣。

    对于验证,我可以理解为什么您有点担心,因为验证是直接在模型上完成的,而其他类型的验证是在服务中完成的。我使用的经验法则是,如果验证需要调用数据库,那么它应该在服务层完成。

    UI 可以直接创建一个新的 GiftCertificate 对象而不通过服务(例如 - 从实体调用参数验证方法)。如果没有,如何执行?

    在 UI 层,当我想创建一个新的礼券时,我是直接从 UI 层调用模型/服务验证(如 IsValidExpirationDate 等)还是先对对象进行水合,然后将其传入以进行验证和然后将某种验证摘要返回给用户界面?

    对于这两个问题,让我们通过一个场景:

    用户输入信息以创建新证书并提交。有字段级验证,因此如果文本框为空或美元金额为负,则会引发验证错误。假设所有字段都有效, Controller 将调用服务 gcService.Save(gc) .

    该服务将检查其他业务逻辑,例如商店是否已经发放了过多的礼券。如果有多个错误代码,它要么返回状态的枚举,要么抛出带有错误信息的异常。

    最后,服务调用 gcRepository.Save(gc) .

    关于c# - 服务层如何适合我的存储库实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6138660/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com