动态可交换数据访问层

我正在编写一个数据驱动的WPF客户端。 客户端通常从WCF服务中提取数据,该服务查询SQL数据库,但我希望选择直接从SQL或其他任意数据源提取数据。

我想出了这个设计,并希望听听你对它是否是最好的设计的看法。

首先,我们要从SQL中提取一些数据对象。

// The Data Object with a single property public class Customer { private string m_Name = string.Empty; public string Name { get { return m_Name; } set { m_Name = value;} } } 

然后我计划使用所有数据访问层应该实现的接口。 假设一个人也可以使用抽象类。 思考?

 // The interface with a single method interface ICustomerFacade { List GetAll(); } 

可以创建SQL实现。

 // Sql Implementation public class SqlCustomrFacade : ICustomerFacade { public List GetAll() { // Query SQL db and return something useful // ... return new List(); } } 

我们还可以创建一个WCF实现。 WCF的问题在于它不使用相同的数据对象。 它创建了自己的本地版本,因此我们必须以某种方式复制细节。 我想可以使用reflection来复制相似字段的值。 思考?

 // Wcf Implementation public class WcfCustomrFacade : ICustomerFacade { public List GetAll() { // Get date from the Wcf Service (not defined here) List wcfCustomers = wcfService.GetAllCustomers(); // The list we're going to return List customers = new List(); // This is horrible foreach(WcfService.Customer wcfCustomer in wcfCustomers) { Customer customer = new Customer(); customer.Name = wcfCustomer.Name; customers.Add(customer); } return customers; } } 

我还计划使用工厂来决定使用哪个立面。

 // Factory pattern public class FacadeFactory() { public static ICustomerFacade CreateCustomerFacade() { // Determine the facade to use if (ConfigurationManager.AppSettings["DAL"] == "Sql") return new SqlCustomrFacade(); else return new WcfCustomrFacade(); } } 

这就是通常使用DAL的方式。

 // Test application public class MyApp { public static void Main() { ICustomerFacade cf = FacadeFactory.CreateCustomerFacade(); cf.GetAll(); } } 

我感谢你的想法和时间。

您有一个非常好的开始,一个非常灵活的软件方法。 您已经遇到了主要问题:数据提供者合同( ICustomerFacade )必须指定所有实施者使用的数据对象。 SQL和WCF数据提供程序都必须返回相同的数据对象。

那部分你标记为“这太可怕了”? 实际上并不是那么糟糕。 你正在迭代两次,是的,但是你这样做是为了提供更强大,更灵活的软件架构。 性能不会那么糟糕(除非你迭代列表中的很多项),你的系统将能够在调用Web服务和直接调用SQL服务器之间切换(一般来说这是不是一个好主意)随意。

消除双重迭代可以做的一件事是让数据合同依赖于数据对象的抽象。 例如,他们会返回ICustomer而不是Customer 。 然后,您的SQL Server对象和您的WCF数据对象可以完全不同,只要它们实现了ICustomer等接口。

其他建议:

  • 你应该考虑为你的集合返回方法返回IList (甚至是IEnumerable )而不是List
  • 你的工厂模式是一个良好的开端,但工厂是如此的2000年代。 :)你可能想考虑使用完整的dependency injection路由; 我建议在Microsoft企业库中使用 Unity。

有两种方法可以解决WCF实现中的数据对象与数据存储区返回的数据对象之间的差异:

  • 在创建WCF代理时,请确保重用引用程序集中的所有类型 (如果使用VS选项而不是直接调用svcutil,则在“高级”对话框中)。

  • 在DTO(数据对象)上有一个Clone()或CopyFrom()类型方法,以便您可以将对象从本地生成的命名空间映射到常规项目命名空间,然后再返回

我会实现选项1 – 选项2肯定会工作,但这是一个非常慢的方法。 有时,当您在生成代理时告诉VS重用引用的类型时,它仍会生成DTO的本地定义 – 在这种情况下,您只需进入生成的Reference.cs类文件并删除所有定义,然后继续使用常规项目命名空间中定义的版本。

除了WCF问题,您似乎走在了正确的轨道上。

我个人认为如果你在谈论.NET到.NET,svcutil.exe是一个反模式。 这是一个没有实际价值的额外突破点。 如果您正在与外部服务或不同平台集成,则svcutil.exe是一个不错的选择。

通常,对于每个服务,应该有一个额外的Contracts程序集,其中包含服务的所有服务接口和datacontracts。 该程序集由服务和客户端引用。 这样,当进行更改时,它们将反映在客户端和服务器中。

http://blog.walteralmeida.com/2010/08/wcf-tips-and-tricks-share-types-between-server-and-client.html