gpt4 book ai didi

c# - ASP.NET Web API破坏存储库/服务模式

转载 作者:行者123 更新时间:2023-11-30 19:25:41 24 4
gpt4 key购买 nike

我是构建Web API的新手,已经达到可以使用一些指导的地步。例如,假设我有一个Product模型和Attachment模型,它们看起来像这样:

 public class Product
{
public Product()
{
Attachments = new List<Attachment>();
}
public int ID { get; set; }
public string Name { get; set; }
public List<Attachment> Attachments { get; set; }
}

public class Attachment
{
public int ID { get; set; }
public string Name { get; set; }
}


请注意, Product模型具有类型为 Attachment的属性列表。在初始化 AttachmentRepository类中的 Property对象时,利用 ProductRepository填充此属性是一种不好的做法吗?

因此,在 ProductRepository中,我将执行以下操作:

Product product = new Product
{
ID = SomeId,
Name = SomeName
Attachments = AttachmentRepository.GetAttachments(SomeName)
};


这是糟糕的设计,而我正在错误地解决吗?我不打算为 Attachment创建控制器,因为没有 Product的上下文就不会有获得附件的用例。

最佳答案

“我不打算为附件创建控制器,因为没有产品的上下文就没有用例来获取附件。”

逆如何?您是否想获得没有附件的产品?

我发现尝试做太多事情的方法不太可重用,因为如果我获得大量产品并且对附件不感兴趣,我不希望也获得所有这些产品的附件的开销。然后,我为设计(无论是我的还是同事的)感到遗憾,添加了一种新方法来获取产品。

在我的控制器中,我将调用GetProduct,然后调用GetAttachments。这将允许您根据需要混合匹配这些内容。

另一种方法是在Products存储库中执行此操作,有一个仅获取产品(GetProducts)的方法,以及另一个调用GetProducts和GetAttachments的GetProductsWithAttachments方法。或者,您当然可以为, includeAttachments = false)使用布尔参数。我不希望数据库层变得混乱。我让Controller成为将它们组合在一起的地方。

我可能甚至在Products模型中都没有Attachments属性,而是有一个特定于控制器的ProductResponseModel,类似于ViewModel。它既具有产品信息又具有Attachments属性,并且可以通过调用两个单独的Repository方法的结果来填充它。

如果在DB层上全部进行了此操作,并且DB层上的Product模型具有Attachments属性,则仅在调用GetProductsWithAttachments时才填充该属性,那么Product模型将填充一半。随着时间的推移添加许多其他类似的属性,您会得到一个令人困惑的模型,因为有时仅根据您调用的存储库的方法填充其某些属性。开发人员必须开始深入研究repo方法,以找出填充内容。如果将促销添加到产品,您将具有GetProductWithAttachments,GetProducts,GetProductWithPromotions,GetProductWithAttachmentsAndPromotions吗?您可以开始了解如何解决这个问题,如果您真的想将其烘焙到存储库中,那么一些默认参数会更好。然而:

推荐:控制器中的组成

这就是为什么我更喜欢让控制器协调整个事情。在控制器内分别调用回购方法。不知道您使用的是REST样式还是Web API控制器中的样式,因此只需考虑以下伪代码即可:

public class ProductController: ApiController
{
public ProductResponseModel Get(int productId)
{
var model = new ProductResponseModel{
Product = ProductRepository.Get(productId);
};
model.Attachments = AttachmentRepository.GetList(model.Product.Name);

// I could have flattened out the Product into its properties instead of having a model.Product,
// but that can be a maintenance problem and requires something like AutoMapper to manage well
return model;
}

}

public class ProductResponseModel {
public Product Product {get;set;}
public IEnumerable<Attachment> Attachments {get;set;}
}


ProductResponseModel是组成示例。它与数据库层之间产生松散耦合,因此您可以随意混合和匹配,即为每个API控制器构建所需数据的模型。 ProductResponseModel本身不是很可重用,可能只是在该控制器内。需要产品数据的不同组合的另一个控制器将具有其自己的SomethingResponseModel并调用单独的存储库方法来填充它。即使我们不能重用我们的* ResponseModels,这也不是什么大问题,因为它们是简单的POCO。从我们的repo方法中获取重用更为重要,并避免它们变得比所需的更为复杂。另外,我们仍然拥有您的简单模型,例如 ProductAttachment,它们是存储库层的一部分,因此调用存储库的每个人都说相同的语言并使用相同的通用类型。因此,不要犯错,就是让您的Repo层返回ProductResponseModel。提取 Product并填充 ProductResponseModel是您控制器的工作。

我使用命名约定* ResponseModel,因为如果我也为action方法具有一个复杂的参数,那么也会有一个* RequestModel。即请求/响应。如果我有一个API方法比REST风格更像RPC风格,例如ProductController.DiscontinueDistribution,它的返回值可能非常专业,因此我将拥有ProductDiscontinueDistributionResponseModel。就像MVC中的ViewModels一样,这些都是简单的POCO。

关于c# - ASP.NET Web API破坏存储库/服务模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27304583/

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