Подтвердить что ты не робот

Лучшие практики баз данных для начинающих

Итак, я довольно новый программист, работающий по направлению на степень бакалавра 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.

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

Спасибо, что прочитали эту гигантскую стену текста.

4b9b3361

Ответ 1

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

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

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

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

Таблицы, объекты и сопоставления Oh My!

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

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

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

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

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

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

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

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

Заключение

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 4

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

  • В то время как код, который вы пишете, будет действительно приятным для работы и действительно поддерживаемым, он включает в себя много работы вверх, это часть причины, по которой мастера так популярны. Они не самые приятные вещи для работы, но сэкономить много времени.
  • Запрос из базы данных - это только начало; Другая причина для использования типизированных наборов данных и мастеров в целом заключается в том, что в большинстве приложений пользователи на какой-то стадии собираются отредактировать вашу информацию и отправить ее для обновления. Одиночные записи прекрасны, но что делать, если ваши данные лучше всего представлены стандартизованным способом с иерархией таблиц 4 в глубину? Написание кода для автоматического создания инструкций обновления/вставки/удаления вручную для всех вызовов, которые являются адскими, поэтому инструменты - единственный путь вперед. напечатанные DataSets будут генерировать весь код для выполнения этих обновлений для вас и иметь очень мощные функции для обработки отключенных (например, на стороне клиента) обновлений/откатов последних изменений.
  • Что говорили последние ребята о SQL-инъекции (которая является серьезным событием в индустрии) и защищая себя, используя DBCommand объект и добавление DbParameters.

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

Ответ 5

Если вы немного боитесь таких вещей, как 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, где "Клиенты" - это пространство имен, а "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.

Ответ 6

Визуальная страница базы данных с помощью combobox и datagrid

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

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);
    }

}

}

Ответ 7

VMV DATABSE

namespace TestDatabase.ViewModel
{
    class MainViewModel : INotifyPropertyChanged
    {
        private Model.Database database;

        private DataTable table;
        public string[] options;
        public string selected;

        public DataTable Table
        {
            get { return table; }
            set { table = value;
                    ChangeProperty("Table"); }
        }

        public string[] Options
        {
            get { return options; }
        }

        public string Selected
        {
            get { return selected; }
            set
            { selected = value;
               Table = database.GetTable(value);
            }
        }

        public MainViewModel()
        {
        database = new Model.Database();
            options = new string[] { "" }; // names of tables

        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void ChangeProperty(string name)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}