Один класс с двумя базами данных - PullRequest
1 голос
/ 25 мая 2011

У меня есть приложение из двух частей.Одна часть - это веб-приложение (C # 4.0), которое работает на хост-компьютере с базой данных MSSQL.Это красиво и стандартно.Другая часть - это приложение Windows, которое запускается локально в нашей сети и обращается как к нашей основной базе данных (Advantage), так и к веб-базе данных.Веб-сайт не имеет доступа к базе данных Advantage.

В настоящее время эта установка работает просто отлично (при условии, что сеть работает), но сейчас мы находимся в процессе перестройки сайта и его обновления с сайта Web Forms /.NET 2.0 / VB до MVC3 /.NET 4.0 / C # сайт.В рамках перестройки мы добавляем ряд новых таблиц, в которых внутренняя база данных содержит все данные, а веб-база данных - их подмножество.

Во внутреннем приложении представлены таблицы в базе данных.классами, которые используют флаги отражения и атрибута для заполнения самих себя.Например:

[AdvantageTable("warranty")]
public class Warranty : AdvantageTable
{
    [Advantage("id", IsKey = true)]
    public int programID;
    [Advantage("w_cost")]
    public decimal cost;
    [Advantage("w_price")]
    public decimal price;

    public Warranty(int id)
    {
        this.programID = id;
        Initialize();
    }
}

Метод Initialize () класса AdvantageTable использует отражение для построения запроса на основе всех ключей и их значений, а затем заполняет каждое поле на основе указанного столбца базы данных.Обновления работают аналогично - мы вызываем AdvantageTable.Update () для любого объекта, и он обрабатывает все записи в базу данных.Он работает довольно хорошо, скрывает все стандартные CRUD и позволяет нам быстро создавать новые классы, когда мы добавляем новую таблицу.Мы бы не хотели его менять, но я не собираюсь полностью исключать это, если есть решение, которое потребует его.

В базе данных сети должна быть эта таблица, но она не нужна.для данных о стоимости.Я мог бы создать отдельный класс, который поддерживается веб-базой данных (с помощью хранимых процедур, рефлексии, LINQ-TO-SQL, объектов данных ADO и т. Д.), Но в объекте Warranty могут быть другие функции, которые я хочу вести себя так женезависимо от того, вызывается ли он с веб-сайта или из внутреннего приложения, без необходимости поддерживать два набора кода.Например, мы могли бы изменить логику того, как мы решаем, какая гарантия распространяется на продукт - я хочу создать и протестировать ее только в одном месте, а не в двух.

Поэтому мой вопрос: Кто-нибудь может придумать хороший способ, позволяющий иногда заполнять этот класс из базы данных Advantage, а иногда и из веб-базы данных? Это не просто вопрос строк подключения, поскольку у них есть два совершенно разных метода доступа (даже помимоотражение).Я подумал о добавлении тегов типа [Web("id")] к тегам Advantage и размещении их только в полях, существующих в веб-базе данных, для обозначения ее столбцов, а затем с помощью какого-то переключателя для управления тем, какой набор логики используется для чтения / записи, но у меня такое чувство, что это будет больно (этот метод безопасен для сети? Как установить флаг перед его созданием?).Поэтому у меня нет идей, которые мне нравятся, и я подозреваю, что есть решение, о котором я даже не подозреваю.Любой вход?

Ответы [ 2 ]

2 голосов
/ 25 мая 2011

Я думаю, что фундаментальная проблема заключается в том, что вы хотите поместить бизнес-логику в объект Warranty, который является объектом уровня данных. Что вы действительно хотите сделать, так это иметь общий контракт данных (в данном случае это может быть интерфейс), который поддерживают оба источника данных, с логикой, инкапсулированной в отдельный класс / уровень, который может работать с любым источником данных. Это устраняет проблему, связанную с попыткой использования одного класса данных с двумя разными источниками данных, путем создания общего контракта данных, который может использовать ваш бизнес-уровень независимо от способа извлечения данных.

Итак, в вашем примере у вас могут быть AdvantageWarranty и WebWarranty, которые оба реализуют IWarranty. У вас есть отдельный класс WarrantyValidator, который может работать с любой гарантией IW, чтобы сообщить вам, действительна ли гарантия для данных условий. Кстати, это дает вам хороший способ заглушить ваши данные, если вы хотите провести модульное тестирование своей бизнес-логики в классе WarrantyValidator.

0 голосов
/ 08 июля 2011

Решение, которое я в итоге придумал, было двойным.Сначала я использовал Linq-to-sql для генерации объектов для каждой веб-таблицы.Затем я извлек новый класс из AdvantageTable с именем AdvantageWebTable<TABLEOBJECT>, который содержит специальный веб-код и добавил специальные веб-атрибуты.Итак, теперь класс выглядит следующим образом:

[AdvantageTable ("Гарантия")]

public class Warranty : AdvantageWebTable<WebObjs.Warranty>
{
    [Advantage("id", IsKey = true)][Web("ID", IsKey = true)]
    public int programID;
    [Advantage("w_cost")][Web("Cost")]
    public decimal cost;
    [Advantage("w_price")][Web("Price")]
    public decimal price;

    public Warranty(int id)
    {
        this.programID = id;
        Initialize();
    }
}

Также есть хуки для заполнения полей только для веб-страниц непосредственно перед сохранением в веб-базе данных, ибудет (но пока нет, поскольку она мне не нужна) функция LoadFromWeb(), которая использует отражение для заполнения полей.

...