LINQ to SQL和N-Tier分层

时间:2016-09-30 05:21:00

标签: c# asp.net wpf linq n-tier-architecture

我的经历让我对程序中的以下结构更加习惯。我们假设它是一个.NET WPF应用程序。您创建一个WPF项目,一个业务逻辑项目(类库),一个数据访问项目(类库)和一个实体项目(类库)。 WPF项目通过业务逻辑层进入数据访问层。实体是轻量级DTO,可以从一层到另一层自由流动。

我的问题是这个。我喜欢LINQ to SQL实体,除非我用它来创建我的实体,我不仅结束了实体关系的直接表,它还将我的实体放入我的数据访问项目并强制我的UI项目引用我的数据访问项目。当然,我可以让我的DataContext内部(我认为它应该是默认情况下),除了我的DTO仍然在我的数据访问项目中,它仍然强制我的UI项目引用我的数据访问项目。

我在这里遗漏了什么,或者是否有另一种方法可以通过LINQ to SQL解除我的DTO,或者我是否应该关心?

1 个答案:

答案 0 :(得分:0)

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

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

因此,在您的情况下UIBusiness logic不应该依赖Data access。被抽象的实体不应该依赖LINQ to SQL

的细节

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

1创建实体抽象项目

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

2创建UI项目

使用的项目业务逻辑抽象
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生成的实体转换为将阻止ICustomer的实例。我发现添加ICustomer是此示例的最简单方法。

注意:DataAccess项目仅依赖于使用LINQ to SQL

实现的抽象依赖性

6创建主项目,它将所有依赖项组合在一起并启动您的UI。

注意:此项目将包含您的应用程序正常工作所需的所有引用。

<强>摘要

使用此方法,您不会依赖LINQ to SQL的详细信息。

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

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