База данных Best-Practices для начинающих - PullRequest
44 голосов
/ 23 июля 2010

Итак, я довольно новый программист, работаю над получением степени бакалавра Comp Sci с очень небольшим опытом работы.В поисках вакансий типа стажировки для моей программы я заметил, что то, что я слышал от нескольких специалистов - «работа с базами данных составляет 90% всех современных заданий в области компьютерных наук» - выглядит так, как будто это действительно так.Тем не менее, моя программа на самом деле не имеет курсов с базами данных до 3-го года обучения, поэтому я стараюсь хотя бы кое-что узнать сам за это время.

Я видел очень мало о SO иИнтернет в целом для кого-то, как я.Кажется, есть тонны руководств по механике чтения и записи данных в базу данных, но мало по соответствующим рекомендациям.Чтобы продемонстрировать, о чем я говорю, и помочь разобраться в моем актуальном вопросе, вот что можно легко найти в Интернете :

public static void Main ()
{
    using (var conn = new OdbcConnection())
    {
        var command = new OdbcCommand();
        command.Connection = conn;
        command.CommandText = "SELECT * FROM Customer WHERE id = 1";
        var dbAdapter = new OdbcDataAdapter();
        dbAdapter.SelectCommand = command;
        var results = new DataTable();
        dbAdapter.Fill(results);
    }

    // then you would do something like
    string customerName = (string) results.Rows[0]["name"]; 
}

и так далее.Это довольно просто понять, но, очевидно, полно проблем.Я начал с кода, подобного этому, и быстро начал говорить что-то вроде: «Ну, кажется, глупо просто иметь повсюду SQL, я должен поместить все это в файл констант».А потом я понял, что глупо иметь одни и те же строки кода повсюду и просто поместить все эти вещи с объектами подключения и т. Д. В метод:

public DataTable GetTableFromDB (string sql)
{
    // code similar to first sample
}    

string getCustomerSql = String.Format(Constants.SelectAllFromCustomer, customerId);
DataTable customer = GetTableFromDB(getCustomerSql);
string customerName = (string) customer.Rows[0]["name"];

Это казалось большим улучшением.Теперь очень легко, скажем, перейти от OdbcConnection к SQLiteConnection.Но эта последняя строка, доступ к данным, все еще казалась неловкой;и все еще трудно изменить имя поля (например, перейти от «name» к «CustName» или что-то в этом роде).Я начал читать о с использованием типизированных наборов данных или пользовательских бизнес-объектов .Я все еще немного сбит с толку всей терминологией, но все равно решил посмотреть на нее. Я полагаю, что глупо полагаться на блестящего Мастера баз данных, который сделает все это за меня (как всвязанные статьи) прежде чем я действительно узнаю, что происходит и почему.Поэтому я сам попробовал это и начал получать такие вещи, как:

public class Customer
{
    public string Name {get; set;}
    public int Id {get; set;}

    public void Populate ()
    {
        string getCustomerSql = String.Format(Constants.SelectAllFromCustomer, this.Id);
        DataTable customer = GetTableFromDB(getCustomerSql);
        this.Name = (string) customer.Rows[0]["name"]; 
    }

    public static IEnumerable<Customer> GetAll()
    {
        foreach ( ... ) { 
            // blah blah
            yield return customer;
        }
    }
}

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

var customer = new Customer(custId);
customer.Populate();
string customerName = customer.Name;

что действительно приятно.И если таблица Customer меняется, изменения в коде должны происходить только в одном месте: внутри класса Customer.

Итак, в конце всего этого бессвязного, мой вопрос таков.Идет ли моя медленная эволюция кода базы данных в правильном направлении?И куда мне идти дальше?Этот стиль хорошо подходит для небольших баз данных, но когда существует множество различных таблиц, выписать все эти классы для каждого из них будет непросто.Я слышал о программном обеспечении, которое может генерировать этот тип кода для вас, но меня все еще смущает жаргон DAL / ORM / LINQ2SQL / etc, и эти огромные куски программного обеспечения являются ошеломляющими.Я ищу хорошие, но не слишком сложные ресурсы, которые могут указать мне правильное направление.Все, что я могу найти по этой теме, - это сложные статьи, которые идут мне на ум, или статьи, которые просто показывают, как использовать мастера наведения и нажатия в Visual Studio и тому подобное.Также обратите внимание, что я ищу информацию о работе с базами данных в коде, а не информацию о дизайне / нормализации баз данных ... есть много хороших материалов по этому вопросу.

Спасибо за чтение этой гигантской стены текста.

Ответы [ 6 ]

18 голосов
/ 23 июля 2010

Очень хороший вопрос, и вы, безусловно, на правильном пути!

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

Вот мой опыт использования устаревших технологий начала 90-х для одного проекта и современных технологий с C # и WPF для другого.

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

Таблицы, объекты и отображения Oh My!

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

В вашем сообщении ваш класс Customer будет действовать как Модель! Итак, вы уже осознали эту выгоду.

Теперь существует множество инструментов / сред (LINQ2SQL, dotConnect, Mindscape LightSpeed), которые напишут весь код вашей модели для вас. В конце они отображают объекты в реляционные таблицы или O / R, как они ссылаются на него.

Как и ожидалось, когда ваша база данных изменится, так же, как и ваши O / R-сопоставления. Как вы уже упоминали, если ваш клиент меняется, вы должны исправить это в одном месте, опять же, почему мы ставим вещи на занятия. В случае моего унаследованного проекта обновление моделей занимало много времени, потому что их было очень много, в то время как в моем новом проекте это всего несколько щелчков мышью, НО в конечном итоге результат остается тем же.

Кто должен знать что?

В моих двух проектах было два разных способа взаимодействия объектов со своими таблицами.

В некоторых лагерях Модели должны знать все о своих таблицах, о том, как себя сохранить, иметь прямой общий доступ к соединению / сеансу и могут самостоятельно выполнять действия, такие как Customer.Delete() и Customer.Save().

Другие лагеря, поместите чтение, запись, удаление, логику в управляющий класс. Например, MySessionManager.Save( myCustomer ). Преимущество этой методологии заключается в возможности легко реализовывать отслеживание изменений на объектах и ​​обеспечивать, чтобы все объекты ссылались на одну и ту же базовую запись таблицы. Однако его реализация является более сложной, чем упомянутый ранее метод локализованной логики класса / таблицы.

Заключение

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

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

8 голосов
/ 23 июля 2010

Ваша эволюция определенно в правильном направлении. Еще несколько вещей для рассмотрения:

  • Используйте подготовленные операторы против String.Format, чтобы связать ваши параметры. Это защитит вас от SQL-инъекций атак.
  • Используйте внешние интерфейсы DBProviderFactory и System.Data.Common для дальнейшего отключения вашей реализации от конкретной базы данных.
  • После этого посмотрите на методы для генерации ваших команд SQL и автоматического сопоставления данных с объектами. Если вы не хотите переходить к большому сложному ORM, поищите простые примеры: ADO.NET ORM за 10 минут , Легкая библиотека ORM или Создание ORM в .NET . Если вы решите пойти по этому пути, в конечном итоге вам будет лучше обслуживать зрелую библиотеку, такую ​​как Entity Framework , Hibernate или SubSonic .
3 голосов
/ 23 июля 2010

Мой совет, если вы хотите узнать о базах данных, первый шаг - забыть о языке программирования, затем - забыть о том, какую базу данных вы используете, и изучить SQL.Конечно, между MySQL, MS SQLserver и Oracle есть много различий, но есть много одинаковых.

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

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

Используйте настольное приложение для выполнения запросов в локальной базе данных (sequel pro, mysqlрабочее место и т. д.), поскольку это намного быстрее, чем загрузка исходного кода на сервер.И получайте от этого удовольствие!

2 голосов
/ 23 июля 2010

Если вы немного боитесь таких вещей, как Linq to SQL и Entity Framework, вы можете сделать полпути между ними и изучить что-то вроде iBATIS.NET. Это просто инструмент отображения данных, который берет на себя часть усилий по управлению подключением к базе данных и отображению ваших результирующих наборов в объекты пользовательского домена.

Вам все еще нужно написать все ваши классы объектов и SQL, но он отображает все ваши данные в классы для вас, используя отражение, и вам не нужно беспокоиться обо всех базовых связях (вы можете легко написать инструмент для генерации ваших классов). Когда вы начнете работать с iBATIS (если вас это заинтересует), ваш код начнет выглядеть следующим образом:

var customer = Helpers.Customers.SelectByCustomerID(1);

Эта функция SelectByCustomerID существует внутри картографа Customers, определение которого может выглядеть следующим образом:

public Customer SelectByCustomerID(int id)
{
    Return Mapper.QueryForObject<Customer>("Customers.SelectByID", id);
}

«Customers.SelectByID» соответствует определению оператора XML, где «Customers» - это пространство имен, а «SelectByID» - это идентификатор карты, содержащей ваш SQL:

<statements>
    <select id="SelectByID" parameterClass="int" resultClass="Customer">
        SELECT * FROM Customers WHERE ID = #value#
    </select>
</statements>

Или, когда вы хотите сменить клиента, вы можете сделать что-то вроде:

customer.FirstName = "George"
customer.LastName = "Costanza"

Helpers.Customers.Update(customer);

LINQ to SQL и Entity Framework становятся более изящными, автоматически создавая SQL для вас. Мне нравится iBATIS, потому что у меня все еще есть полный контроль над SQL и как выглядят мои доменные объекты.

Проверьте iBATIS (теперь перенесено в Google под именем MyBatis.NET). Еще один замечательный пакет - NHibernate , который на несколько шагов впереди iBATIS и ближе к полной версии ORM.

2 голосов
/ 23 июля 2010

ИМХО, вы определенно идете в правильном направлении, чтобы действительно хорошо работать с поддерживаемым кодом! Однако я не уверен, что подход будет масштабироваться до реального приложения. Несколько мыслей, которые могут быть полезны

  1. В то время как код, который вы пишете, будет очень приятным для работы и реально поддерживаемым, он требует много работы заранее, и это одна из причин, почему мастера так популярны. Они не самая приятная вещь для работы, но экономят много времени.
  2. Запросы из базы данных - это только начало; Другая причина использования типизированных наборов данных и мастеров в целом заключается в том, что в большинстве приложений пользователи на каком-то этапе собираются редактировать вашу информацию и отправлять ее для обновления. Отдельные записи хороши, но что, если ваши данные лучше всего представлены в нормализованном виде с иерархией таблиц 4? Написание кода для автоматической генерации операторов update / insert / delete вручную для всех этих вызовов будет адским, поэтому инструменты - единственный путь вперед. Типизированные DataSets сгенерируют весь код для выполнения этих обновлений для вас и обладают очень мощными функциями для обработки отключенных (например, на стороне клиента) обновлений / откатов последних изменений.
  3. То, что последние парни говорили о внедрении SQL (что является СЕРЬЕЗНО большим событием в отрасли) и защите себя с помощью объекта DBCommand и добавления DbParameters.

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

0 голосов
/ 11 сентября 2017

Визуальная страница базы данных только с комбинированным списком и сеткой данных

пространство имен

TestDatabase.Model

{класс базы данных

{
    private MySqlConnection connecting;
    private MySqlDataAdapter adapter;

    public Database()
        {
        connecting = new MySqlConnection("server=;uid=;pwd=;database=;");
        connecting.Open();
        }

    public DataTable GetTable(string tableName)
    {
        adapter = new MySqlDataAdapter("SELECT * FROM "+ tableName, connecting);
        DataSet ds = new DataSet();
        adapter.Fill(ds);

        adapter.UpdateCommand = new MySqlCommandBuilder(adapter).GetUpdateCommand(); 
        adapter.DeleteCommand = new MySqlCommandBuilder(adapter).GetDeleteCommand(); 

        ds.Tables[0].RowChanged += new DataRowChangeEventHandler(Rowchanged);
        ds.Tables[0].RowDeleted += new DataRowChangeEventHandler(Rowchanged);

        return ds.Tables[0];
    }
    public void Rowchanged(object sender, DataRowChangeEventArgs args)
    {
        adapter.Update(sender as DataTable);
    }

}

}

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