C# 可以使用接口将数据传递到数据层吗

C# 可以使用接口将数据传递到数据层吗,c#,object,domain-driven-design,C#,Object,Domain Driven Design,所以。这可能是个愚蠢的问题,但是 我仅限于使用不支持EntityFramework的数据库,但我仍然希望将数据层分离到单独的程序集中。这意味着我需要共享域对象值,同时避免业务层和数据层之间的循环引用。因此,我想知道构建一个持久性接口存储库是否可以接受,该存储库可以由业务层实现,并相互独立地传递给数据层 示例如下: // Business Layer public class Customer: IPersistableCustomer { private string name;

所以。这可能是个愚蠢的问题,但是

我仅限于使用不支持EntityFramework的数据库,但我仍然希望将数据层分离到单独的程序集中。这意味着我需要共享域对象值,同时避免业务层和数据层之间的循环引用。因此,我想知道构建一个持久性接口存储库是否可以接受,该存储库可以由业务层实现,并相互独立地传递给数据层

示例如下:

// Business Layer
public class Customer: IPersistableCustomer
{
    private string name;

    public string Name{ get { return this.name; } }

    public void persist()
    {
        dataLayer.StoreCustomerInstance(this);
    }
}

// DataLayer
public StoreCustomerInstance(IPersistableCustomer persistableCustomer)
{
    // Do storage stuff
}

// Interface repository
public interface IPersistableCustomer
{
    string Name { get; }
}

我几乎可以肯定这是个糟糕的主意,但我不知道为什么。我很想知道人们的想法,看看潜在的陷阱在哪里。

您在示例中所做的是将域对象隐藏在接口后面。您应该做的是将数据层隐藏在接口后面。数据层的这种抽象通常被称为存储库模式

在业务层中,定义域类和存储库接口:

public class Customer
{
    public Customer(string name)
    {
        this.Name = name;
    }

    public string Name { get; private set; }
}

public interface ICustomerRepository
{
    void Save(Customer customer);
}
请注意,Customer类没有任何持久性逻辑。存储库接口也没有;它只定义了数据层的契约

合同的实施在数据层进行:

public class SqlCustomerRepository : ICustomerRepository
{
    public void Save(Customer customer)
    {
        // Persistence logic
    }
}
此时,数据层需要对业务层进行引用,而不是反过来

您可以在应用程序层中将这两个层绑定在一起:

class CustomerForm
{
    private readonly ICustomerRepository customerRepository;

    // This class declares a dependency on any ICustomerRepository
    public CustomerForm(ICustomerRepository customerRepository)
    {
        this.customerRepository = customerRepository;
    }

    public void PersistCustomer()
    {
        Customer customer = CreateCustomerFromUserInput();

        this.customerRepository.Save(customer);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Dependency injection, usually done via a DI container
        var customerRepository = new SqlCustomerRepository();
        var form = new CustomerForm(customerRepository);

        form.PersistCustomer();
    }
}
当我和你面对同样的问题时,我发现关于这个问题的文章非常有价值。它解释了如何以防止与数据层紧密耦合的方式设置应用程序的体系结构

为数据层使用接口的另一个优点是,它允许您对大部分代码进行单元测试,而无需实际运行数据库。您可以简单地模拟存储库接口

几年前,我曾经为我的域对象使用过接口。我不后悔,因为它教会了我如何不去做。但这是唯一的好事;这是大量的额外工作和维护,没有任何真正的好处:)

我不同意“在这一点上,数据层需要引用业务层”,因为如果要垂直绘制层,则数据位于底部,业务位于数据顶部。从架构的角度来看,这与您需要的正好相反。你调用,你从不调用,业务比数据更不稳定,业务应该调用数据。