4

Нашей команде было предложено написать веб-интерфейс для существующего бэкэнд SQL Server, который имеет свои корни в Access.Способы обхода плохой схемы базы данных?

Одним из требований/ограничений является то, что мы должны ограничить изменения в SQL-сервере. Мы можем создавать представления и хранимые процедуры, но нам было предложено оставить таблицы/столбцы как есть.

Бэкэнд SQL не идеален. Большинство отношений являются неявными из-за отсутствия внешних ключей. В некоторых таблицах отсутствуют первичные ключи. Названия таблиц и столбцов являются непоследовательными и включают в себя символы, такие как пробелы, слэши и знаки фунта.

Помимо получения новой работы или просьбы пересмотреть это требование, может ли кто-либо предоставить какие-либо хорошие шаблоны для устранения этого недостатка?

ПРИМЕЧАНИЕ. Мы будем использовать SQL Server 2005 и ASP.NET с .NET Framework 3.5.

+9

Я считаю, что техническое название шаблона проектирования здесь будет «хлопнуть сверху» –

+0

Спасибо за выбор мой ответ, как * в * ответ. Я добавил немного больше кода, чтобы проиллюстрировать ObjectDataSources, так как вы его выбрали. –

+0

@KM - разве это не анти-шаблон? Я также google'd SQL «Plop сверху», и эта страница была наверху. :) – Mayo

ответ

6

Простота: убедитесь, что у вас надежные слои доступа к данным и бизнес-логике. Вы должны избегать соблазна напрямую обращаться к базе данных с вашего кода ASPX!

Даже с надежной схемой базы данных, теперь я делаю так, чтобы практика никогда не работала с SQL в кодах - практика, которая развивалась только после того, как она усвоила, что у нее есть свои недостатки.

Вот несколько советов, чтобы помочь процессу:

Во-первых, исследовать класс ObjectDataSource. Это позволит вам создать надежный BLL, который все еще может управлять элементами управления, такими как GridView, без использования прямого SQL. Они выглядят так:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
    OldValuesParameterFormatString="original_{0}" 
    SelectMethod="GetArticles" <-- The name of the method in your BLL class 
    OnObjectCreating="OnObjectCreating" <-- Needed to provide an instance whose constructor takes arguments (see below) 
    TypeName="MotivationBusinessModel.ContentPagesLogic"> <-- The BLL Class 
    <SelectParameters> 
     <asp:SessionParameter DefaultValue="News" Name="category" <-- Pass parameters to the method 
      SessionField="CurPageCategory" Type="String" /> 
    </SelectParameters> 
</asp:ObjectDataSource> 

Если построение экземпляра класса BLL необходимо передать аргументы, вам нужна ссылка OnObjectCreating. В вашем коде, реализовать это как так:

public void OnObjectCreating(object sender, ObjectDataSourceEventArgs e) 
    { 
     e.ObjectInstance = new ContentPagesLogic(sessionObj); 
    } 

Далее реализации BLL требует еще несколько вещей, которые я спасу вас от Googling. Вот реализация, которая соответствует вышеперечисленным вызовам.

namespace MotivationBusinessModel <-- My business model namespace 
{ 
    public class ContentPagesItem <-- The class that "stands in" for a table/query - a List of these is returned after I pull the corresponding records from the db 
    { 
     public int UID { get; set; } 
     public string Title { get; set; } <-- My DAL requires properties but they're a good idea anyway 
     ....etc... 
    } 

    [DataObject] <-- Needed to makes this class pop up when you are looking up a data source from a GridView, etc. 
    public class ContentPagesLogic : BusinessLogic 
    { 
     public ContentPagesLogic(SessionClass inSessionObj) : base(inSessionObj) 
     { 
     } 

     [DataObjectMethodAttribute(DataObjectMethodType.Select, true)] <-- Needed to make this *function* pop up as a data source 
     public List<ContentPagesItem> GetArticles(string category) <-- Note the use of a generic list - which is iEnumerable 
     { 
      using (BSDIQuery qry = new BSDIQuery()) <-- My DAL - just for perspective 
      { 
       return 
        qry.Command("Select UID, Title, Content From ContentLinks ") 
         .Where("Category", category) 
         .OrderBy("Title") 
         .ReturnList<ContentPagesItem>(); 
       // ^-- This is a simple table query but it could be any type of join, View or sproc call. 
      } 
     } 
    } 
} 

Во-вторых, легко добавить DAL/BLL DLLs к вашему проекту в качестве дополнительных проектов, а затем добавить ссылку на основной веб-проекта. Выполнение этого не только дает вашим DAL и BLL собственные идентификаторы, но и делает модульное тестирование.

В-третьих, я почти не признаю этого, но это может быть одно место, где Microsoft Entity Framework пригодится. Обычно мне не нравится Linq to Entities, но это позволяет указать спецификацию отношений данных, отсутствующих в вашей базе данных.

Наконец, я могу понять, почему изменений на вашу структуру db (например, движущиеся поля вокруг) было бы проблемой, но добавлять новые ограничения (особенно индексы) не должно быть. Они боятся, что внешний ключ в конечном итоге приведет к ошибкам в другом программном обеспечении? Если так ... это не такая хорошая вещь; вы должны иметь некоторую боль, чтобы знать, где лежит болезнь, нет?

По крайней мере, вы должны настаивать на возможности добавлять индексы по мере необходимости по соображениям производительности.Кроме того, я согласен с другими в том, что Views могут значительно продвинуться в создании более разумной структуры. Однако, этого действительно недостаточно в конечном итоге. Итак ... продолжайте и создавайте Views (Хранимые процедуры тоже), но вы должны еще избегать кодирования непосредственно в базе данных. В противном случае вы по-прежнему остаетесь привязкой вашей реализации к схеме базы данных и избежание ее в будущем будет сложнее, чем если вы изолируете взаимодействия db с DAL.

+0

Просто создайте второй проект, который обращается к базе данных и использует код dll для использования кода. –

+0

lol - Я работал над этой частью ответа, когда вы оставили свой комментарий. Это один из тех «катящихся» ответов, где, если я жду, чтобы сказать все, что я хотел бы сказать, это будет за 10 минут до того, как я попаду в очередь. Вы правы на отметке, хотя ... –

+0

Использование DAL должно быть заданным, независимо от состояния базовой схемы. –

1

кто может предоставить какие-либо хорошие модели для решения этого недостатка

кажется, что вам было отказано единственная возможность «решать этот недостаток».

Я предлагаю добавить логику проверки целостности в ваши ближайшие хранимые процедуры. Внешние ключи, уникальные ключи, все это можно выполнить вручную. Не хорошая работа, но выполнимая.

0

Если вы используете LinqToSql, вы можете вручную создать отношения в DBML. Кроме того, вы можете переименовывать объекты в соответствии с вашим предпочтительным стандартом (вместо косых черт и т. Д.).

8

Представления и синонимы могут получить вас до сих пор, но исправление базовой структуры явно потребует больше работы.

Я бы, конечно, попробовал еще раз убедить заинтересованные стороны в том, что не устраняя проблем, которые они налагают на технический долг, и это создаст более медленную скорость продвижения кода, в конечном итоге до такой степени, когда долг может быть искалечен. Пока вы можете обойти это, долг будет там.

Даже с уровнем доступа к данным основные проблемы в базе данных, такие как упомянутые вами ключи/индексы, могут вызвать проблемы при попытке масштабирования.

+4

+1 для технического долга –

+0

Я согласен с этим настроением, но Майо, возможно, не имеет права требовать, чтобы этот долг был оплачен. Если это так, это решение просто не будет применяться. –

+0

+1, поскольку я, конечно, считаю, что это наиболее правильный подход, но я не могу выбрать его как правильный ответ. Я попробую еще раз спросить, могут ли они поразить взгляды, которые отражают старые таблицы, что дает мне свободу для новых таблиц. В противном случае я буду работать с ответом Марка. :) – Mayo

1

Одна вещь, которую вы можете сделать, это создать множество представлений, чтобы имена таблиц и столбцов были более разумными, избавляясь от неприятных символов. Я предпочитаю не иметь пробелов в именах таблиц и столбцов, поэтому мне не нужно использовать квадратные скобки везде.

К сожалению, у вас возникнут проблемы из-за отсутствия внешних ключей, но вы можете захотеть создать индексы в столбце, такие как имя, которое должно быть уникальным, чтобы помочь.

По крайней мере, на яркой стороне не должно быть большого количества подключений, поэтому ваш SQL должен быть простым.

2

Поскольку вы заявили, что вам нужно «ограничить» изменения в схеме базы данных, кажется, что вы можете добавить поле первичного ключа к тем таблицам, которые их не имеют. Предполагая, что существующие приложения не выполняют никаких инструкций «SELECT * ...», это не должно нарушать существующий код. После этого создайте представления таблиц, которые находятся в едином подходе, и настройте триггеры в представлении для операторов INSERT, UPDATE и DELETE. Он будет иметь незначительный удар производительности, но это позволит создать единый интерфейс с базой данных. И тогда любые новые добавленные таблицы должны соответствовать новому стандарту.

Очень хакерский способ обработки, но это подход, который я использовал в прошлом с ограниченным доступом для изменения существующей схемы.

0

Я бы начал с индексированных представлений на каждой из таблиц, определяющих первичный ключ. И, возможно, более индексированные представления в тех местах, где вы хотите индексировать таблицы. Это начнет решать некоторые проблемы с производительностью и все ваши проблемы с именами.

Я рассматривал бы эти представления так, как если бы они были необработанными таблицами. Это то, что должны обрабатывать ваши хранимые процедуры или уровень доступа к данным, а не базовые таблицы.

С точки зрения обеспечения соблюдения правил целостности, я предпочитаю помещать их на уровне доступа к данным в коде с минимальными проверками целостности на уровне базы данных. Если вы предпочитаете проверки целостности в базе данных, вы должны широко использовать sprocs для их принудительного применения.

И не стоит недооценивать возможности найти новую работу ;-)

2

Я бы сделать «конец вокруг», если сталкиваются с этой проблемой. Скажите своим боссам, что лучший способ справиться с этим - создать базу данных «отчетности», которая по сути является динамической копией оригинала. Вы должны создать сценарии или отдельное приложение для передачи данных, чтобы обновить базу данных отчетов с изменениями в оригинале и распространить изменения, внесенные в вашу базу данных, на исходное, а затем написать свой веб-интерфейс для связи только с вашей «отчетной» базой данных.

После установки этой установки вы сможете бесплатно рационализировать свою копию базы данных и вернуть ее в сферу здравомыслия, добавив первичные ключи, индексы, нормализуя ее и т. Д. Даже в краткосрочной перспективе , это лучшая альтернатива, чем попытка написать свой веб-интерфейс для связи с плохо разработанной базой данных, и в долгосрочной перспективе ваша версия базы данных, вероятно, в конечном итоге заменит оригинал.

4

Я был здесь раньше. Руководство полагает, что быстрее будет использовать старую схему и двигаться вперед. Я попытаюсь убедить их, что новая схема приведет к тому, что это и все будущие разработки будут быстрее и надежнее.

Если вы все еще сбиты и не можете выполнить полную редизайн, подходите к ним с компромиссом, где вы можете переименовывать столбцы и таблицы, добавлять PK, FK и индексы. Это не займет много времени и поможет много.

не хватает этого, вам придется измельчить его. Я бы инкапсулировал все в хранимых процедурах, где вы можете добавлять всевозможные проверки для обеспечения целостности данных. Я все равно буду красться во всех PK, FK, индексах и переименованиях столбцов, насколько это возможно.

+0

Я бы согласился только на ключи и индексы. ИМО, это не реляционная база данных без них. – Greg

0

Это действительно зависит от того, сколько у вас автоматизированного покрытия. Если у вас мало или вообще нет, вы не можете вносить какие-либо изменения, не разбирая вещи (если это не было уже для начала).

Я бы порекомендовал вам разумно реорганизовать вещи по мере внесения других изменений, но не делайте крупномасштабного рефакторинга в БД, он будет вводить ошибки и/или создавать слишком много работы по тестированию.

Некоторые вещи, такие как отсутствующие первичные ключи, действительно трудны для работы и должны быть исправлены раньше, чем позже. Непоследовательные названия таблиц в принципе можно терпеть навсегда.

0

Я делаю много интеграции данных с плохо разработанными базами данных, и метод, который я принял, заключается в использовании базы данных с перекрестными ссылками, которая находится рядом с исходным источником db; это позволяет мне хранить представления, хранимые процедуры и код обслуживания в связанной базе данных, не касаясь исходной схемы. Единственное исключение, которое я делаю, касаясь исходной схемы, заключается в том, что при необходимости я буду использовать индексы; однако я стараюсь избегать этого, если это вообще возможно.

Красота этого метода заключается в том, что вы можете изолировать новый код от старого кода, и вы можете создавать представления, которые адресуют плохие определения сущностей, именования ошибок и т. Д. Без нарушения другого кода.

Stu