簡體   English   中英

動態可交換數據訪問層

[英]Dynamic swappable Data Access Layer

我正在編寫一個數據驅動的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<Customer> GetAll();
}

可以創建SQL實現。

// Sql Implementation
public class SqlCustomrFacade : ICustomerFacade
{
    public List<Customer> GetAll()
    {
        // Query SQL db and return something useful
        // ...

        return new List<Customer>();
    }
}

我們還可以創建一個WCF實現。 WCF的問題在於它不使用相同的數據對象。 它創建了自己的本地版本,因此我們必須以某種方式復制細節。 我想可以使用反射來復制相似字段的值。 思考?

// Wcf Implementation
public class WcfCustomrFacade : ICustomerFacade
{
    public List<Customer> GetAll()
    {
        // Get date from the Wcf Service (not defined here)
        List<WcfService.Customer> wcfCustomers = wcfService.GetAllCustomers();

        // The list we're going to return
        List<Customer> customers = new List<Customer>();

        // 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 然后,只要他們實現了ICustomer等接口,您的SQL Server對象和WCF數據對象就可以完全不同。

其他建議:

  • 你應該考慮為你的集合返回方法返回IList (甚至IEnumerable )而不是List
  • 你的工廠模式是一個良好的開端,但工廠是如此的2000年代。 :)您可能要考慮使用完整的依賴注入路由; 我建議在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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM