【发布时间】:2013-06-09 19:14:22
【问题描述】:
在工作中,我开始开发一个遗留的企业级应用程序,该应用程序仍在生产中,由于设计不佳和不稳定,过去几个月一直停滞不前。
所以我们已经开始使用 EF5 并将一些设计模式/层应用到我们的应用程序中。
我很难理解的是:在我们的案例中,服务层到底应该做什么?它会过度架构,还是会在不增加不必要的复杂性的情况下提供一些好处?
让我们向您展示我们目前的成果:
- 我们引入了 EF(带有 POCO 的 Code First)来映射我们的旧数据库(运行良好)
- 我们已经为我们在新数据层中所需的大部分内容创建了存储库(具体实现,我认为使用通用存储库分离关注点没有任何好处..)
现在在特定情况下,它是关于计算文章的价格 - 通过直接从 arcile 或从文章所在的组获取价格(如果没有指定价格)。它变得越来越复杂,因为还涉及不同的价目表(取决于订单的完整价值)并且取决于也可以有特价等的客户。
所以我的主要问题是:谁负责获得正确的价格?
我的想法是: 订单必须知道它包含的项目。另一方面,这些商品必须知道它们的价格是多少,但订单必须不知道如何计算商品的价格,只需要汇总它们的成本。
目前我的代码的摘录:
ArticlePrice(POCO,即将由 Fluid API 交换的映射)
[Table("artikeldaten_preise")]
public class ArticlePrice : BaseEntity
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("einheit")]
public int UnitId { get; set; }
[ForeignKey("UnitId")]
public virtual Unit Unit { get; set; }
[Column("preisliste")]
public int PricelistId { get; set; }
[ForeignKey("PricelistId")]
public virtual Pricelist Pricelist { get; set; }
[Column("artikel")]
public int ArticleId { get; set; }
[ForeignKey("ArticleId")]
public virtual Article Article { get; set; }
public PriceInfo PriceInfo { get; set; }
}
文章价格存储库:
public class ArticlePriceRepository : CarpetFiveRepository
{
public ArticlePriceRepository(CarpetFiveContext context) : base(context) {}
public IEnumerable<ArticlePrice> FindByCriteria(ArticlePriceCriteria criteria)
{
var prices = from price in DbContext.ArticlePrices
where
price.PricelistId == criteria.Pricelist.Id
&& price.ArticleId == criteria.Article.Id
&& price.UnitId == criteria.Unit.Id
&& price.Deleted == false
select price;
return prices.ToList();
}
}
public class ArticlePriceCriteria
{
public Pricelist Pricelist { get; set; }
public Article Article { get; set; }
public Unit Unit { get; set; }
public ArticlePriceCriteria(Pricelist pricelist, Article article, Unit unit)
{
Pricelist = pricelist;
Article = article;
Unit = unit;
}
}
PriceService(确实有一股可怕的代码味道......)
public class PriceService
{
private PricelistRepository _pricelistRepository;
private ArticlePriceRepository _articlePriceRepository;
private PriceGroupRepository _priceGroupRepository;
public PriceService(PricelistRepository pricelistRepository, ArticlePriceRepository articlePriceRepository, PriceGroupRepository priceGroupRepository)
{
_pricelistRepository = pricelistRepository;
_articlePriceRepository = articlePriceRepository;
_priceGroupRepository = priceGroupRepository;
}
public double GetByArticle(Article article, Unit unit, double amount = 1, double orderValue = 0, DateTime dateTime = new DateTime())
{
var pricelists = _pricelistRepository.FindByDate(dateTime, orderValue);
var articlePrices = new List<ArticlePrice>();
foreach (var list in pricelists)
articlePrices.AddRange(_articlePriceRepository.FindByCriteria(new ArticlePriceCriteria(list, article, unit)));
double price = 0;
double priceDiff = 0;
foreach (var articlePrice in articlePrices)
{
switch (articlePrice.PriceInfo.Type)
{
case PriceTypes.Absolute:
price = articlePrice.PriceInfo.Price;
break;
case PriceTypes.Difference:
priceDiff = priceDiff + articlePrice.PriceInfo.Price;
break;
}
}
return (price + priceDiff) * amount;
}
public double GetByPriceGroup(PriceGroup priceGroup, Unit unit)
{
throw new NotImplementedException("not implemented yet");
}
//etc. you'll get the point that this approach might be completely WRONG
}
我最后的问题是: 如何正确建模我的问题?是否正确,我正在对代码进行过度架构? 我的服务层将如何正确显示?我宁愿拥有 ArticlePriceService、ArticleGroupPriceService 等吗?但是谁会连接这些部分并计算出正确的价格呢?会不会,例如是具有“GetPrice”方法的 OrderItemService 的责任吗?但话又说回来,orderItemService 必须知道其他服务..
请尝试为我提供有关架构的可能解决方案,以及哪个对象/层做什么。
如果您需要更多信息,请随时问我其他问题!
【问题讨论】:
-
如果您可以将问题的大小减少到原始问题的一半甚至三分之一,您将会有更多的人阅读此...
-
我对建议持开放态度,但我真的不知道如何在不删除与我的问题有关的重要信息的情况下减少它:/
标签: c# entity-framework architecture service-layer