Динамический сменяемый уровень доступа к данным - PullRequest
3 голосов
/ 07 мая 2010

Я пишу управляемый данными клиент 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();
    }
}

Я ценю ваши мысли и время.

Ответы [ 3 ]

4 голосов
/ 07 мая 2010

У вас очень хорошее начало для действительно гибкого подхода к вашему программному обеспечению. Вы уже столкнулись с основной проблемой вашего подхода: в контракте с поставщиком данных (ICustomerFacade) должны быть указаны объекты данных, которые используются всеми исполнителями. И ваши поставщики данных SQL, и WCF должны возвращать одинаковые объекты данных.

Эта часть, которую вы называете "это ужасно"? Это на самом деле не так уж и плохо. Да, вы повторяете дважды, но вы делаете это для обеспечения более сильной и гибкой архитектуры программного обеспечения. Производительность не будет такой плохой (если вы не перебираете множество элементов в списке), и ваша система сможет переключаться между вызовом веб-службы и вызовом SQL-сервера напрямую (независимо от того, хорошая идея в общем) по желанию.

Единственное, что вы могли бы сделать, чтобы исключить двойную итерацию, - это привязать ваш контракт данных к абстракциям ваших объектов данных. Например, они вернут ICustomer, а не Customer. Тогда ваши объекты SQL Server и ваши объекты данных WCF могут быть разными объектами, если они реализуют интерфейсы ICustomer и т. Д.

Дополнительные предложения:

  • Вам следует рассмотреть возможность возврата IList (или даже IEnumerable) вместо List для методов, возвращающих коллекцию.
  • Ваш фабричный образец - хорошее начало, но фабрики - это 2000-е годы. :) Возможно, вы захотите пройти полный маршрут внедрения зависимостей; Я бы предложил Unity в Microsoft Enterprise Library .
1 голос
/ 07 мая 2010

Существует два способа устранить разницу между объектами данных в реализации WCF и тем, что возвращается из хранилища данных:

  • при создании прокси-сервера WCF убедитесь, что вы повторно используете все типы в ссылочных сборках (в диалоговом окне «Дополнительно», если используется опция VS вместо прямого вызова svcutil).

  • имеет метод типа Clone () или CopyFrom () в ваших DTO (объектах данных), так что вы можете отобразить объекты из локально сгенерированного пространства имен в обычное пространство имен проекта и обратно

Я бы реализовал вариант 1 - вариант 2 обязательно сработает, но это очень медленный способ сделать это. Иногда, когда вы говорите VS повторно использовать ссылочные типы при создании прокси, он все равно будет генерировать локальные определения DTO - в этом случае вы можете просто зайти в сгенерированный файл класса Reference.cs, удалить все определения и продолжить используя версии, определенные в обычном пространстве имен проекта.

Помимо проблем с WCF, вы, похоже, на правильном пути.

0 голосов
/ 04 декабря 2014

Я лично считаю svcutil.exe антипаттерном, если вы говорите .NET в .NET. Это дополнительный переломный момент без реальной ценности. Если вы интегрируетесь с внешней службой или другой платформой, svcutil.exe - хороший выбор.

Как правило, для каждой службы должна быть дополнительная сборка контрактов, которая содержит все интерфейсы сервисов и контракты данных для сервиса. На эту сборку ссылаются как служба, так и клиент. Таким образом, при внесении изменений они будут отражены как на клиенте, так и на сервере.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...