繁体   English   中英

LINQ to SQL和N层分层

[英]LINQ to SQL and N-Tier layering

我的经验使我更习惯于程序中的以下结构。 假设它是一个.NET WPF应用程序。 您创建一个WPF项目,一个业务逻辑项目(类库),一个数据访问项目(类库)和一个实体项目(类库)。 WPF项目通过业务逻辑层到达数据访问层。 实体是轻量级的DTO,可以在各层之间自由流动。

我的问题是这个。 我喜欢LINQ to SQL实体,除了使用LINQ to SQL实体创建实体外,我不仅会获得一个直接的表与实体的关系,还将实体放入我的数据访问项目中,并强制我的UI项目引用到我的数据访问项目。 当然,除了我的DTO仍在我的Data Access项目中而且它仍然迫使我的UI项目引用我的Data Access项目之外,我可以使其DataContext内部(无论如何我都认为默认情况下应该如此)。

我是否在这里遗漏了某些东西,或者还有其他方法可以使我的DTO与LINQ to SQL相提并论?

如果我们遵循依赖倒置原则

  • 高级模块不应依赖于低级模块。 两者都应依赖抽象。
  • 抽象永远不要依赖细节。 细节应取决于抽象。

因此,在您的情况下, UIBusiness logic不应依赖于Data access 抽象的实体永远不要依赖LINQ to SQL细节

然后,我们从高层开始设计应用程序

1创建实体抽象项目

public interface ICustomer
{
    int Id { get; set; }
}

2创建UI项目使用的Project业务逻辑抽象

public interface ICustomerService
{
    List<ICustomer> LoadTop50();
}

3创建UI项目

3.1创建使用ICustomerICustomerService来显示个人信息的UI逻辑

注意:UI仅依赖于抽象,不了解其他层。

4创建业务项目

4.1创建用于获取数据的DataAccess抽象

    namespace Business.DataAccessAbstractions
    {
        public interface ICustomerDataAccess
        {
            List<ICustomer> Load(int topAmount);
        }
    }

4.2实现ICustomerService ,它使用ICustomerDataAccess抽象

public class CustomerService : ICustomerService
{
    private DataAccessAbstractions.ICustomerDataAccess _dataAccess;

    public CustomerService(DataAccessAbstractions.ICustomerDataAccess dataAccess)
    {
        _dataAccess = dataAccess;
    }

    public IEnumerable<ICustomer> LoadTop50()
    {
        const int TOP_NUMBER = 50;
        return _dataAccess.Load(TOP_NUMBER);
    }
}

注意: Business项目为数据访问创建抽象。 并实现抽象,UI将使用该抽象来显示数据。

5创建DataAccess项目

5.1使用LINQ to SQL创建实体。

5.2实现Business.DataAccessAbstractions.ICustomerDataAccess接口。

5.2.1使由LINQ to SQL生成的实体实现ICustomer

    [Table(Name="dbo.Customer")]
    public partial class Customer : INotifyPropertyChanging, 
                                    INotifyPropertyChanged, 
                                    ICustomer
    {
        private int _Id;

        [Column(Storage="_Id", 
                AutoSync=AutoSync.OnInsert, 
                DbType="Int NOT NULL IDENTITY", 
                IsPrimaryKey=true, 
                IsDbGenerated=true)]
        public int Id
        {
            get
            {
                return this._Id;
            }
            set
            {
                if ((this._Id != value))
                {
                    this.OnIDChanging(value);
                    this.SendPropertyChanging();
                    this._Id = value;
                    this.SendPropertyChanged("Id");
                    this.OnIDChanged();
                }
            }
        }
    }

您只需ICustomer添加到已实现的接口列表中。 或创建/生成一些“映射逻辑”,将LINQ to SQL生成的实体转换LINQ to SQL的实例将ICustomer 我发现添加ICustomer是此示例的最简单方法。

注意: DataAccess项目仅依赖于通过使用LINQ to SQL实现的抽象

6创建Main项目 ,它将所有依赖项混合在一起并启动UI。

注意:该项目将包含您的应用程序正常运行所需的所有参考。

摘要

使用这种方法,您的UI将不再依赖LINQ to SQL细节。

使用这种方法,您可以自由地修改DataAccess的实现,直到修改不会破坏高级抽象为止。

当然,如果您决定添加要在UI中使用的Customer的新数据字段,则需要修改整个依赖关系链。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM