C# 如果我想显示数据库中的数据,我是否应该在BLL项目类中创建与DAL项目中的poco类相同的类,并将其返回到UI项目?

C# 如果我想显示数据库中的数据,我是否应该在BLL项目类中创建与DAL项目中的poco类相同的类,并将其返回到UI项目?,c#,asp.net-mvc,entity-framework,architecture,C#,Asp.net Mvc,Entity Framework,Architecture,我有一个架构问题。我有DAL项目和poco类(数据库中的等效表)、BLL项目和UI项目。UI项目引用BLL项目,BLL项目引用DAL项目 我想在UI中显示项目数据,例如来自表Product from database的数据我是否应该在BLL项目类中创建与DAL项目中的poco类相同的类,并将其返回到UI项目并显示它? 这是DAL中的mine poco类(数据库中的等效表): 在BLL中,我创建了与上述poco类相同的业务对象: public class ProductBO { publi

我有一个架构问题。我有DAL项目和poco类(数据库中的等效表)、BLL项目和UI项目。UI项目引用BLL项目,BLL项目引用DAL项目

我想在UI中显示项目数据,例如来自表Product from database的数据我是否应该在BLL项目类中创建与DAL项目中的poco类相同的类,并将其返回到UI项目并显示它?

这是DAL中的mine poco类(数据库中的等效表):

在BLL中,我创建了与上述poco类相同的业务对象:

public class ProductBO
{
    public int ID { get; set; }
    public string Name { get; set; }
    public String Address { get; set; }
}
在BLL中,我还有一个从DAL获取产品并将其映射到业务对象的方法—ProductBO:

public class ProductService
{
    public List<ProductBO> GetAllProducts()
    {
        List<ProductBO> productsBO = new List<ProductBO>();

        using (var context = NorthwindFactory.CreateContext())
        {
            List<Product> products = context.Product.ToList();

            foreach (var product in products)
            {
                productsBO.Add(new ProductBO { ID = product.ID, Address = product.Address, Name = product.Name });
            }
        }

        return productsBO;
    }
}
公共类产品服务
{
公共列表GetAllProducts()
{
List productsBO=新列表();
使用(var context=NorthwindFactory.CreateContext())
{
List products=context.Product.ToList();
foreach(产品中的var产品)
{
productsBO.Add(新ProductBO{ID=product.ID,Address=product.Address,Name=product.Name});
}
}
返回产品sbo;
}
}
现在在控制器的UI项目中,我从BLL调用服务,它返回列表,在视图中,我可以使用业务对象ProductBO显示数据

@model IEnumerable<WebApplication1.BLL.BusinessObjects.ProductBO>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Address)
        </th>
    </tr>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Address)
        </td>
    </tr>
}
</table>
@model IEnumerable
@DisplayNameFor(model=>model.Name)
@DisplayNameFor(model=>model.Address)
@foreach(模型中的var项目){
@DisplayFor(modelItem=>item.Name)
@DisplayFor(modelItem=>item.Address)
}

这是正确的体系结构方法吗?

您应该在BLL项目中定义POCO(域)对象,因为它们是业务对象

您的DAL应该引用BLL,而不是相反

就我个人而言,我是将您的域置于应用程序中心的应用程序的追随者。添加的任何图层都只应向内参照,而不应向外参照。因此,根据这个定义,你的BLL是中心,没有引用任何东西。添加DAL层,它只能向内引用,因此它可以引用BLL。UI层也只是引用BLL,而不是DAL,因为DAL是一个实现细节。

嗯,没有一种正确的方法。但我倾向于避免创建一组DAL类。现代的ORM允许使用POCO类。是的,有一些限制(如枚举),但不值得为每个业务实体创建两个副本并在它们之间进行映射。所以,我使用位于业务逻辑组件中的单个POCO实体。实体框架与该实体一起工作,从数据库保存并加载该实体。没有映射

表示层是不同的。通常,同一实体在不同页面上有多个表示形式。您还可以使用不同的数据注释属性来设置对视图模型的限制,或某些UIT提示。这会用特定于UI的逻辑污染您的业务实体。此外,您通常需要显示格式化或修改后的数据,如FullName,而不是Person实体的FirstName和LastName。因此,这里我不使用我的POCO业务实体,而是创建视图模型

对于您的产品样本,此方法将如下所示:

  • 业务逻辑程序集具有POCO实体
    产品
  • 持久性程序集引用业务逻辑程序集并使用相同的
    产品
  • UI项目有不同的视图模型
    ProductViewModel
    BriefProductViewModel
    等。它还负责
    产品
    和视图模型之间的映射。注意-手动映射非常耗时。我建议您使用一些映射库,如AutoMapper或ValueInjector

如果是我,我会在DAL和BLL之间共享域对象。这样可以减少重复代码的数量。对于视图,如果需要,我将创建与之交互的视图模型,但这些视图模型也使用域对象。通过这种方式,您也不需要在
Product
ProductBO
之间进行转换,为什么DAL需要引用BLLMaybe来使用POCO对象,并将它们存储在DB中。在OPs示例中,POCO位于DAL中,所以可能正如@3dd所说的那样-我应该使用POCO类和DAL、BLL创建新项目,UI项目应该引用具有poco类的项目?我对另一个答案的评论也适用于这个。对于一个可能从未实施过国际奥委会的人来说,这看起来一定像是“黑魔法”。你的解释一定有问题。我假设您的BL程序集引用“persistence assembly”来使用它,您还说您的persistence程序集引用BL来使用
产品。这是一个明确的循环参考。VS如何处理它?(一定有一些隐藏的成分:DI),项目wuth接口?)我已经看到@Maarten的答案使用了相同的技术。我想知道+1为什么会提到额外的“持久性”模型通常不值得付出额外的努力——ORM已经在某种程度上扮演了这个角色。附加的抽象层总是在灵活性和复杂性/成本之间进行权衡。另请参阅本文:@JotaBe“我想您的BL程序集引用了持久性程序集”=>为什么?BL不应该决定如何或何时持久化其对象。它不需要了解持久层。@guillaume31。我试图理解这是怎么可能的。例如,如果您使用BL“Order.New(some data)”下订单,那么业务层应该将其存储在某个位置,因此它应该调用Persisntence层,因此它应该对该层具有依赖性。我明白
@model IEnumerable<WebApplication1.BLL.BusinessObjects.ProductBO>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Address)
        </th>
    </tr>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Address)
        </td>
    </tr>
}
</table>