使用具有不同层的 LINQ 意味着我无法访问特定类型

Posted

技术标签:

【中文标题】使用具有不同层的 LINQ 意味着我无法访问特定类型【英文标题】:Using LINQ with different layers means I can't access a specific type 【发布时间】:2019-05-15 22:27:03 【问题描述】:

我的解决方案中有 3 层:

DAL(正在使用 LINQ 访问我的数据库) 业务层 Winform

在我的 DAL 中,我从我的数据库中返回一个具有特定类型的 List,并且我在我的 BLL 中做同样的事情。

当我想在我的 UI 中使用我的函数时,我得到了错误:

“Reservation”类型是在未引用的程序集中定义的...

现在我想避免在我的 UI 中引用我的 DAL。

由于我是新手,无法在网上找到明确的答案,请谁能帮帮我?

我的 DAL 函数

public static List<Reservation> SelectListReservation()

    try
    
        List<Reservation> lstReservation = new List<Reservation>();
        lstReservation = oExamenSgbdEntities.Reservations.ToList();
        return lstReservation;
    
    catch (Exception e)
    
        throw e;
    

我的 BLL 函数

public static List<DataAccess.Reservation> GetListReservation()

    try
    
        List<DataAccess.Reservation> lstToReturn = new List<Reservation>();
        lstToReturn = GetListReservation();
        return lstToReturn;
    
    catch (Exception e)
    
        throw e;
    

如何在 UI 中调用 BL 函数:

var lstRes = Manage.GetListReservation();

【问题讨论】:

无意义的try…catch…throw块有什么用? 他不知道你可以告诉调试器在第一个异常时中断。 顺便说一句,如果你这样做,你应该只做一个throw;而不是throw e; @MatthewWhited 是正确的,throw e will reset the stack trace。 那我不应该使用 throw e 吗?还是我应该只在特定层中使用它?我只想在最后的 MessageBox 中显示错误。 【参考方案1】:

从您问题中的详细信息来看,您使用的是Traditional N-Layer Architecture。在这个架构中,UI层依赖于BLL,而BLL依赖于DAL。那应该是您的参考结构:UI 项目引用 BLL 项目,BLL 项目引用 DAL 项目。

这对您意味着,您不能在您的 UI 中使用 DAL 中的类; UI 不应该知道 DAL 的实现,因为 DAL 可能会更改(例如从 SQL Server 数据库移动到 Oracle 数据库)。因此,为了从 DAL 获取数据到 BLL,您需要在 BLL 中创建一个模型类,并将 DAL 类中的所有数据映射到它。

例如,在您的 BLL 中,您需要添加一个 ReservationModel 类,该类将映射到 DAL 中的 Reservation 类:

public class ReservationModel

    // Add the same properties that are in the Reservation class in 
    // the DAL to this class. The properties below are just for example
    public int ReservationId  get; set; 
    public DateTime StartDate  get; set; 
    public DateTime EndDate  get; set; 
    public int CustomerId  get; set; 

然后在 BLL 中,更改 GetListReservation() 方法以返回一个 ReservationModel,其中包含从 DAL 中的 Reservation 类映射的所有数据:

public static List<ReservationModel> GetListReservation()

    var reservationModels = new List<ReservationModel>();

    foreach (var reservation in SelectListReservation())
    
        reservationModels.Add(new ReservationModel
        
            // Again, these are made-up properties for illustration purposes
            ReservationId = reservation.ReservationId,
            StartDate = reservation.StartDate,
            EndDate = reservation.EndDate,
            CustomerId = reservation.CustomerId
        );
    

    return reservationModels;

【讨论】:

我喜欢这个答案。但是,我相信如果隐藏在接口后面,UI 可以在不显式引用 DAL 的情况下使用 DAL 类 @JuanR 我可能会遗漏一些东西,但我认为这不可能仅仅因为界面在哪里?如果在 DAL 中,UI 看不到;如果它在 BLL 中,则 DAL 看不到它;如果它在 UI 中,则 DAL 和 BLL 看不到它。 BLL 必须是 UI 和 DAL 之间的中介(这很好,因为您可以更换 DAL 或 UI 并仍然使用核心业务逻辑)。 我过去所做的是有一个单独的接口组件。然后所有其他人都可以引用此程序集(例如SomeProject.Core)。 很高兴我能帮上忙。【参考方案2】:

一种解决方案是创建一个数据传输对象 (DTO) 库,用于包装来自数据层的对象,因为它们是在单独的程序集中定义的。然后,业务层可以调用数据库并将结果转换为这些新类。

这打破了表示层和数据层之间的依赖关系,还允许您自定义从数据 -> 业务和/或业务 -> 表示中公开的内容(您可以将数据库中的多个对象聚合成一个,并且您可以在可能的情况下暴露更小的对象)。

您可以在此处阅读更多信息:Create Data Transfer Objects (DTOs)

【讨论】:

【参考方案3】:

如果你切入 DAL、BL 和 P,你的 BL 方法不能返回与你的 DAL 相同的类型。

P 使用 BL,BL 使用 DAL

因此 P 是从 DAL 中抽象出来的

如果包含在 DAL 中,则保留仅由 BL 使用

解耦您的 DAL 类型和您的 BL 类型或选择不同的架构。

【讨论】:

以上是关于使用具有不同层的 LINQ 意味着我无法访问特定类型的主要内容,如果未能解决你的问题,请参考以下文章

无法使用多态性访问具体类的唯一属性

使用 Linq.Expression 访问具有动态 lambda 的嵌套属性

具有潜在分组层的 C# LINQ 问题

C# Linq 计算具有特定值的 XML 段

具有匿名类型和用户定义类型的 LINQ 选择查询

无法为具有集合属性的类编写正确的 Linq 查询 - 出现 EfCore5 翻译错误