-
Posts
60 -
Joined
-
Last visited
-
Days Won
2
Content Type
Profiles
Forums
Downloads
Posts posted by Malboro
-
-
Всем привет!!
Увидел тутер на английском по Entity Framework на MySql и решил сообразить свой вариант на Великом и Могучем, только для базы данных Postgresql. Надеюсь это кому-то будет полезным. Работать мне еще 3 часа, а значит должен успеть.
Поехали
Нам потребуется:
- Visual Studio
- Голова
- Руки
- Немного времени
Установка необходимых библиотек
Первое что нам нужно сделать это открыть наш Visual Studio и загрузить необходимые библиотеки. Для этого открываем диспетчер пакетов NuGet, ищем и устанавливаем следующие библиотеки:
- gtanetwork.api
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Tools
- Npgsql
- Npgsql.EntityFrameworkCore.PostgreSQL
- Newtonsoft.Json

Вот общая картина:

Создание структуры классов
Создадим следующие классы:
- Character - основной класс, модель которого мы и будем сохранять в базе
- Finances - будет хранить в себе информацию о финансах нашего игрока.
- States - будет содержать информацию о состоянии персонажа
- Item - будет представлять класс вещи из нашего инвентаря
- Login - отвечающий за авторизацию персонажа
- Registration - ... за его регистрацию
- Db - будет хранить подключение к базе данных
- AppDbContext - основной класс который и будет содержать практически все настройки для нашей базы данных
Посмотреть более подробно содержимое можно скачав проект с репозитория на github.
Для тех кто в теме:
git clone https://github.com/SirEleot/EFCore_Npgsql.git
Для начала давайте настроим подключение к базе данных, для этого создадим новый класс AppDbContext который будет включать в себя все основные настройки касающиеся базы данных. Давайте пока просто посмотрим на его содержимое, а чуть позже разберем более детально:
class AppDbContext : DbContext { //сторка подключения к бд. private static string ConnectionString = "Host=localhost;Port=5432;Database=test;Uid=test;Password=test;"; //настройка подключения к базе данных protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql(ConnectionString); } //Добавляем класс для сохранения в дб //дочерние классы добавлять не нужно EFCore сам их подхватит public DbSet<Character> Characters { get; set; } // тут находится конфигурация наших сохроняемых классов protected override void OnModelCreating(ModelBuilder modelBuilder) { //настроим игнорирование свойства Data из класса Character //вот так игнорируются свойства класса modelBuilder.Entity<Character>().Ignore(c => c.Date); //также добавим будем игнорировать класс Item //так как он входит в состав нашего класса, то EFCore попытается для него создать таблицу //мы же решили что будем сохраять инвентарь в виде json строки //вот так игнорируются классы modelBuilder.Ignore<Item>(); //здесь здесь пример того как обработать данные при сохранении //мы будем преобразовывать массив с вещамивв строку json modelBuilder .Entity<Character>()//выбираем объект из контекста у нас он 1 .Property(c => c.Inventory)//выбираем свойство .HasConversion( //определяем кастомные методы для обработки данных i => JsonConvert.SerializeObject(i), // при сохранении i => JsonConvert.DeserializeObject<List<Item>>(i) // при загрузке ); //рассмотрим как сохранить отдельный объект в нашем случае Finance //в одной таблице с основным классом modelBuilder.Entity<Character>()//выбираем объект из контекста у нас он 1 .OwnsOne(c => c.Finance);//определяем свойство которое мы хотим добавить к текущей таблице в базе дбазе данных } } }
Настройка базы данных
Думаю что с ConnectionString проблемы возникнуть не должно. Хотя :
- Host=localhost; - расположение базы данных
- Port=5432; - прослушиваемый порт
- Database=test; - название базы данных
- Uid=test; - имя пользователя
- Password=test; - и соответственно пароль
В функции OnConfiguring задаются настройки, которые необходимы при инициализации базы данных. В нашем случае это строка подключения к базе данных. Так же тут можно настроить автоматическую миграцию, но об этом поговорим позже.
Давайте разберем содержимое нашего основного класса:
class Character { //для элементов хранящихся в отдельных таблицах обязательно наличие поля с атрибутом primary key //но в EFCore достаточно создать для класса свойство Id и он сделает все за вас public int Id { get; set; } public string Social { get; set; } public string Name { get; set; } public string Lasname { get; set; } public string Password { get; set; } // поместим финансовую модель в одну таблицу с персонажем //состояние персонажа будет автоматом помещено в отдельную таблицу //все настройки производятся в классе AppDbContext public Finances Finance { get; set; } public States State { get; set; } //так же мы сохраним список вещей в основную таблицу персонажа в виде строки JSON //настройка так же в классе AppDbContext public List<Item> Inventory { get; set; } //это свойство создано для примера, мы его будем игнорировать при сохранении данных в базу //не поверите но это тоже настроим в классе AppDbContext public DateTime Date { get; set; } }
Тут мы видим различные свойства персонажа: логин, имя, фамилия и пароль (не забывайте шифровать пароль при сохранении). Стоит обратить внимание на обязательный параметр Id, он необходим для корректного сохранения в базе данных. Все классы, которые предполагают сохранение в отдельной таблице, должны содержать свойство Id, либо любое другое предназначенное для хранения уникального ключа(но это другая история).
Перейдем непосредственно к настройкам. Для начала нужно оповестить EF Core о том что мы собираемся сохранить данный класс, для этого добавим свойство Characters типа DbSet<T>, где Т - класс нашей модели Character
public DbSet<Character> Characters { get; set; }
Составим небольшой план действий. Допустим, что мы хотим чтобы информация о финансах находилась в одной таблице с нашим персонажем, а его состояние наоборот было вынесено в отдельную таблицу. Так же мы хотим что бы коллекция Inventory хранилась в виде строки Json. Еще у нас есть свойство Date и мы не хотим сохранять его в базе данных.
План "накидали", теперь давайте попробуем воплотить его в код. Итак по порядку:
Первым рассмотрим включаемый класс Finances:
class Finances { //для элементов сохраняющихся в оттдельных таблицах обязательно поле с primary key //Достаточно создать свойство Id и EFCore сделает все за вас //В конкретном случае мы не добавляем свойство Id так как Finance будет помещен в одну таблицу с Character //смотрите настройки в классе AppDbContext //public int Id { get; set; } public int Bank { get; set; } = 5000; public int Cash { get; set; } = 500; //добавить деньги на счет public bool AddBank(int amount) { Bank += amount; return true; } //списать деньги со счета public bool SubBank(int amount) { if (amount > Bank) return false; Bank -= amount; return true; } //...... }
Наш класс содержит информацию о счете игрока, а так же методы взаимодействия со счетом. Наличие методов никак не повлияет на корректность сохраняемых данных. Мы решили что класс Finances будет сохранятся в одной таблице с персонажем, а это значит что свойство Id можно опустить.
Настройки записываются в переопределенном методе OnModelCreating класса AppDbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder. ....... }Перейдем непосредственно к настройке Finance:
modelBuilder.Entity<Character>()//выбираем объект из контекста у нас он 1 .OwnsOne(c => c.Finance);//определяем свойство которое мы хотим добавить к текущей таблице в базе дбазе данных
тут мы при помощи метода OwnsOne(c => c.Finance) говорим EF Core, что свойство Finance следует сохранять в одной таблице с Character.

Обратите внимание на 6 и 7 колонки это и есть свойства нашего класса Finances включенного в состав таблицы Characters. Так же обратите внимание на 1 колонку Id с пометкой [PK], это и есть наше обязательное одноименное свойство.
Дальше у нас идет класс States:
class States { //для элементов сохраняющихся в отдельных таблицах обязательно поле с primary key //Достаточно создать свойство Id и EFCore сделает все за вас public int Id { get; set; } public int Health { get; set; } = 100; public int Armor { get; set; } = 100; }
Ef Core, по умолчанию, пытается создать отдельную таблицу для каждого класса, включенного в состав нашего основного объекта, поэтому нам остается только создать уникальное свойство Id.

Для нашего класса States была автоматически создана соответствующая таблица в базе данных, а ссылка на нее была добавлена в основную таблицу в колонку 8 с названием StateId
Далее давайте рассмотрим пользовательские преобразование данных. У нас есть свойство Inventory которое является коллекцией классов Item, и мы решили сохраить его в виде строки json. Для этого в метод OnModelCreating класса AppDbContext добавим следующие строки кода:
modelBuilder .Entity<Character>()//выбираем объект из контекста у нас он 1 .Property(c => c.Inventory)//выбираем свойство .HasConversion( //определяем кастомные методы для обработки данных i => JsonConvert.SerializeObject(i), // при сохранении i => JsonConvert.DeserializeObject<List<Item>>(i) // при загрузке );
За это отвечает метод HasConversion(), где первым параметром передается метод обработки данных при сохранении, а вторым при загрузке. В нашем случае это будет сериализация коллекции в строку при сохранении и обратно при загрузке. Для примера мы использовали методы из библиотеки Newtonsoft.Json

В результате у нас добавилась колонка Inventory с типом text которая хранит нашу сериализованую коллекцию в виде строки, конечно пустой массив это не лучший пример, позже сделаю новый скриншот, если не забуду.
Последним пунктом по настройке базы данных у нас будет исключение ненужных нам свойства Date, и класса Item. Так как класс Item включен в состав нашего основного класса Character, то EF Core попытается создать для него отдельную таблицу, а она нам не нужна. Тут все просто:
modelBuilder.Ignore<Item>();
Вот так мы добавляем класс Item в список игнорируемых классов
modelBuilder.Entity<Character>().Ignore(c => c.Date);
А вот так Свойство Date класса Character
Так выглядит общая структура созданной нами базы данных:

Миграции базы данных
Миграция базы данных это автоматическое созданная структура базы данных для нашего класса, в нашем случае SQL. Миграцию можно настроить как в автоматическом режиме, при запуске приложения, так и производить миграцию в ручном режиме. В рамках этого гайда мы не будем настраивать автоматический режим. В ручном режиме вы наглядно увидите что происходит.
Для начала нам нужно отобразить окно с названием "Консоль диспетчера пакетов" для этого жмякаем : Вид -> Другие окна -> Консоль диспетчера пакетов

В левом нижнем углу появится окно с названием, как ни странно "Консоль диспетчера пакетов". Давайте там пропишем команду для создания миграции: add-migration test_001
где add-migration это сама команда а test_001 это название будущей миграции и нажмем Enter

Если мы все сделали правильно, мы должны увидеть сообщение следующего характера повествующее нам о том, что отменить это действие можно введя в консоли команду remove-migration:

В проекте будет создана папка с файлами миграции

Далее, чтобы развернуть саму базу данных введем команду update-database. Если строка подключения настроена корректна и база данных доступна вы увидите следующее сообщение об успешной миграции:

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

Дальнейшая работа с миграциями отличается больше чем никак: При изменении структуры класса мы создаем новую миграцию при помощи команды add-migration изменяя только имя самой миграции test_002 к примеру. Имя может быть произвольным, но уникальным. Для обновления базы введите команду update-database . В папке Migrations будет вестись история ваших миграций и вы в любой момент сможете откатить базу данных к любому этапу, используя команду update-database с именем миграции до которой нужно произвести откат изменений. Например последняя миграция у нас test_002 а нам нужно откатить до версии test_001, для этого мы должны ввести команду: update-database test_001
Думаю на этом этапе с миграциями мы закончим, если что-то непонятно по миграциям пишите в комментариях. Далее рассмотрим непосредственно работу с базой.
Работа с базой данных
Сохранение
Для того чтобы добавить данные о персонаже в базу, нам нужно создать экземпляр нашего класса и добавить его в контекст при помощи метода Add(), после чего нужно сохранить все изменения из контекста данных непосредственно в базу при помощи метода SaveChanges()
public void OnRegistration(Client client, string name, string lastname, string password) { //не забываем про хеширование пароля перед сохранением в бд //создаем нового персонажа Character Char = new Character { Social = client.SocialClubName, Name = name, Lasname = lastname, Password = password, Finance = new Finances(), State = new States(), Inventory = new List<Item>(), Date = DateTime.Now }; //добавляем его в контекст данных Db.Instance.Add(Char); //сохранянем изменения в базе данных Db.Instance.SaveChanges(); }
Для обновления данных нужно воспользоваться методом Update() для обновления данных о персонаже, и так же зафиксировать их при помощи метода SaveChanges()
//обновляем данные в контексте Db.Instance.Update(Char); //и сохраняем в бд Db.Instance.SaveChanges();
Загрузка
С загрузкой дела немного обстоят по другому. Для начала нам не нужны данные находящиеся в другой таблице, будь то состояние персонажа в нашем примере, его кастомизация или что-то еще. Нам будет достаточно информации о его логине и пароле. Рассмотрим пример загрузки данных из бд:
public void OnRegistration(Client client, string pwd) { //Получаем персонажа из бд Character Char = Db.Instance.Characters.SingleOrDefault(c=>c.Social == client.SocialClubName); //если записи соответствующей кретерию нашего запроса нет вернется Null if (Char == null) return; //проверяем пароль на совпадение (не забываем про хеш) if (Char.Password == pwd) { //подгружаем зависимые классы вынексеные в отдельную таблицу Db.Instance.Entry(Char).Reference(c => c.State).Load(); //создаем ссылку на нашу модель игрока client.SetData("Character", Char); //загружаем игрока //.............. } else { //если не прошел проверку отправляем на повторный логин //................ } }
В этом методе, в первую очередь, мы получаем первое значение соответствующее критерию нашего запроса и возвращаем экземпляр объекта Character со свойствами взятыми из бд. Свойство State, хранящееся в отдельно таблице, будет иметь значение null,его нужно будет явно запросить из базы, но на данном этапе нам достаточно данных чтобы сверить полученный от клиента пароль с паролем из бд (не забывайте про шифрование паролей). Если ни одна одна запись не будет соответствовать критерию нашего запроса вернется Null, это скажет нам о том что пользователя с данным логином не существует.
Если значение пароля совпадает то пришло время подгрузить недостающие данные. Делаем это мы при помощи метода Load() для необходимого свойства - в нашем случае это State
Db.Instance.Entry(Char).Reference(c => c.State).Load();
На этом этапе наш класс загружен в полном объеме и готов к употреблению. Нам осталось сохранить ссылку на него что бы в дальнейшем можно было манипулировать данными.
На этом думаю закончу, если что-то непонятно пишите, постараюсь дополнить. А я устал - я ухожу...
-
2
-
Всем привет!!
Увидел тутер на английском по Entity Framework на MySql и решил сообразить свой вариант на Великом и Могучем, только для базы данных Postgresql. Надеюсь это кому-то будет полезным. Работать мне еще 3 часа, а значит должен успеть.
Поехали
Нам потребуется:
- Visual Studio
- Голова
- Руки
- Немного времени
Установка необходимых библиотек
Первое что нам нужно сделать это открыть наш Visual Studio и загрузить необходимые библиотеки. Для этого открываем диспетчер пакетов NuGet, ищем и устанавливаем следующие библиотеки:
- gtanetwork.api
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Tools
- Npgsql
- Npgsql.EntityFrameworkCore.PostgreSQL
- Newtonsoft.Json

Вот общая картина:

Создание структуры классов
Создадим следующие классы:
- Character - основной класс, модель которого мы и будем сохранять в базе
- Finances - будет хранить в себе информацию о финансах нашего игрока.
- States - будет содержать информацию о состоянии персонажа
- Item - будет представлять класс вещи из нашего инвентаря
- Login - отвечающий за авторизацию персонажа
- Registration - ... за его регистрацию
- Db - будет хранить подключение к базе данных
- AppDbContext - основной класс который и будет содержать практически все настройки для нашей базы данных
Посмотреть более подробно содержимое можно скачав проект с репозитория на github.
Для тех кто в теме:
git clone https://github.com/SirEleot/EFCore_Npgsql.git
Для начала давайте настроим подключение к базе данных, для этого создадим новый класс AppDbContext который будет включать в себя все основные настройки касающиеся базы данных. Давайте пока просто посмотрим на его содержимое, а чуть позже разберем более детально:
class AppDbContext : DbContext { //сторка подключения к бд. private static string ConnectionString = "Host=localhost;Port=5432;Database=test;Uid=test;Password=test;"; //настройка подключения к базе данных protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql(ConnectionString); } //Добавляем класс для сохранения в дб //дочерние классы добавлять не нужно EFCore сам их подхватит public DbSet<Character> Characters { get; set; } // тут находится конфигурация наших сохроняемых классов protected override void OnModelCreating(ModelBuilder modelBuilder) { //настроим игнорирование свойства Data из класса Character //вот так игнорируются свойства класса modelBuilder.Entity<Character>().Ignore(c => c.Date); //также добавим будем игнорировать класс Item //так как он входит в состав нашего класса, то EFCore попытается для него создать таблицу //мы же решили что будем сохраять инвентарь в виде json строки //вот так игнорируются классы modelBuilder.Ignore<Item>(); //здесь здесь пример того как обработать данные при сохранении //мы будем преобразовывать массив с вещамивв строку json modelBuilder .Entity<Character>()//выбираем объект из контекста у нас он 1 .Property(c => c.Inventory)//выбираем свойство .HasConversion( //определяем кастомные методы для обработки данных i => JsonConvert.SerializeObject(i), // при сохранении i => JsonConvert.DeserializeObject<List<Item>>(i) // при загрузке ); //рассмотрим как сохранить отдельный объект в нашем случае Finance //в одной таблице с основным классом modelBuilder.Entity<Character>()//выбираем объект из контекста у нас он 1 .OwnsOne(c => c.Finance);//определяем свойство которое мы хотим добавить к текущей таблице в базе дбазе данных } } }
Настройка базы данных
Думаю что с ConnectionString проблемы возникнуть не должно. Хотя :
- Host=localhost; - расположение базы данных
- Port=5432; - прослушиваемый порт
- Database=test; - название базы данных
- Uid=test; - имя пользователя
- Password=test; - и соответственно пароль
В функции OnConfiguring задаются настройки, которые необходимы при инициализации базы данных. В нашем случае это строка подключения к базе данных. Так же тут можно настроить автоматическую миграцию, но об этом поговорим позже.
Давайте разберем содержимое нашего основного класса:
class Character { //для элементов хранящихся в отдельных таблицах обязательно наличие поля с атрибутом primary key //но в EFCore достаточно создать для класса свойство Id и он сделает все за вас public int Id { get; set; } public string Social { get; set; } public string Name { get; set; } public string Lasname { get; set; } public string Password { get; set; } // поместим финансовую модель в одну таблицу с персонажем //состояние персонажа будет автоматом помещено в отдельную таблицу //все настройки производятся в классе AppDbContext public Finances Finance { get; set; } public States State { get; set; } //так же мы сохраним список вещей в основную таблицу персонажа в виде строки JSON //настройка так же в классе AppDbContext public List<Item> Inventory { get; set; } //это свойство создано для примера, мы его будем игнорировать при сохранении данных в базу //не поверите но это тоже настроим в классе AppDbContext public DateTime Date { get; set; } }
Тут мы видим различные свойства персонажа: логин, имя, фамилия и пароль (не забывайте шифровать пароль при сохранении). Стоит обратить внимание на обязательный параметр Id, он необходим для корректного сохранения в базе данных. Все классы, которые предполагают сохранение в отдельной таблице, должны содержать свойство Id, либо любое другое предназначенное для хранения уникального ключа(но это другая история).
Перейдем непосредственно к настройкам. Для начала нужно оповестить EF Core о том что мы собираемся сохранить данный класс, для этого добавим свойство Characters типа DbSet<T>, где Т - класс нашей модели Character
public DbSet<Character> Characters { get; set; }
Составим небольшой план действий. Допустим, что мы хотим чтобы информация о финансах находилась в одной таблице с нашим персонажем, а его состояние наоборот было вынесено в отдельную таблицу. Так же мы хотим что бы коллекция Inventory хранилась в виде строки Json. Еще у нас есть свойство Date и мы не хотим сохранять его в базе данных.
План "накидали", теперь давайте попробуем воплотить его в код. Итак по порядку:
Первым рассмотрим включаемый класс Finances:
class Finances { //для элементов сохраняющихся в оттдельных таблицах обязательно поле с primary key //Достаточно создать свойство Id и EFCore сделает все за вас //В конкретном случае мы не добавляем свойство Id так как Finance будет помещен в одну таблицу с Character //смотрите настройки в классе AppDbContext //public int Id { get; set; } public int Bank { get; set; } = 5000; public int Cash { get; set; } = 500; //добавить деньги на счет public bool AddBank(int amount) { Bank += amount; return true; } //списать деньги со счета public bool SubBank(int amount) { if (amount > Bank) return false; Bank -= amount; return true; } //...... }
Наш класс содержит информацию о счете игрока, а так же методы взаимодействия со счетом. Наличие методов никак не повлияет на корректность сохраняемых данных. Мы решили что класс Finances будет сохранятся в одной таблице с персонажем, а это значит что свойство Id можно опустить.
Настройки записываются в переопределенном методе OnModelCreating класса AppDbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder. ....... }Перейдем непосредственно к настройке Finance:
modelBuilder.Entity<Character>()//выбираем объект из контекста у нас он 1 .OwnsOne(c => c.Finance);//определяем свойство которое мы хотим добавить к текущей таблице в базе дбазе данных
тут мы при помощи метода OwnsOne(c => c.Finance) говорим EF Core, что свойство Finance следует сохранять в одной таблице с Character.

Обратите внимание на 6 и 7 колонки это и есть свойства нашего класса Finances включенного в состав таблицы Characters. Так же обратите внимание на 1 колонку Id с пометкой [PK], это и есть наше обязательное одноименное свойство.
Дальше у нас идет класс States:
class States { //для элементов сохраняющихся в отдельных таблицах обязательно поле с primary key //Достаточно создать свойство Id и EFCore сделает все за вас public int Id { get; set; } public int Health { get; set; } = 100; public int Armor { get; set; } = 100; }
Ef Core, по умолчанию, пытается создать отдельную таблицу для каждого класса, включенного в состав нашего основного объекта, поэтому нам остается только создать уникальное свойство Id.

Для нашего класса States была автоматически создана соответствующая таблица в базе данных, а ссылка на нее была добавлена в основную таблицу в колонку 8 с названием StateId
Далее давайте рассмотрим пользовательские преобразование данных. У нас есть свойство Inventory которое является коллекцией классов Item, и мы решили сохраить его в виде строки json. Для этого в метод OnModelCreating класса AppDbContext добавим следующие строки кода:
modelBuilder .Entity<Character>()//выбираем объект из контекста у нас он 1 .Property(c => c.Inventory)//выбираем свойство .HasConversion( //определяем кастомные методы для обработки данных i => JsonConvert.SerializeObject(i), // при сохранении i => JsonConvert.DeserializeObject<List<Item>>(i) // при загрузке );
За это отвечает метод HasConversion(), где первым параметром передается метод обработки данных при сохранении, а вторым при загрузке. В нашем случае это будет сериализация коллекции в строку при сохранении и обратно при загрузке. Для примера мы использовали методы из библиотеки Newtonsoft.Json

В результате у нас добавилась колонка Inventory с типом text которая хранит нашу сериализованую коллекцию в виде строки, конечно пустой массив это не лучший пример, позже сделаю новый скриншот, если не забуду.
Последним пунктом по настройке базы данных у нас будет исключение ненужных нам свойства Date, и класса Item. Так как класс Item включен в состав нашего основного класса Character, то EF Core попытается создать для него отдельную таблицу, а она нам не нужна. Тут все просто:
modelBuilder.Ignore<Item>();
Вот так мы добавляем класс Item в список игнорируемых классов
modelBuilder.Entity<Character>().Ignore(c => c.Date);
А вот так Свойство Date класса Character
Так выглядит общая структура созданной нами базы данных:

Миграции базы данных
Миграция базы данных это автоматическое созданная структура базы данных для нашего класса, в нашем случае SQL. Миграцию можно настроить как в автоматическом режиме, при запуске приложения, так и производить миграцию в ручном режиме. В рамках этого гайда мы не будем настраивать автоматический режим. В ручном режиме вы наглядно увидите что происходит.
Для начала нам нужно отобразить окно с названием "Консоль диспетчера пакетов" для этого жмякаем : Вид -> Другие окна -> Консоль диспетчера пакетов

В левом нижнем углу появится окно с названием, как ни странно "Консоль диспетчера пакетов". Давайте там пропишем команду для создания миграции: add-migration test_001
где add-migration это сама команда а test_001 это название будущей миграции и нажмем Enter

Если мы все сделали правильно, мы должны увидеть сообщение следующего характера повествующее нам о том, что отменить это действие можно введя в консоли команду remove-migration:

В проекте будет создана папка с файлами миграции

Далее, чтобы развернуть саму базу данных введем команду update-database. Если строка подключения настроена корректна и база данных доступна вы увидите следующее сообщение об успешной миграции:

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

Дальнейшая работа с миграциями отличается больше чем никак: При изменении структуры класса мы создаем новую миграцию при помощи команды add-migration изменяя только имя самой миграции test_002 к примеру. Имя может быть произвольным, но уникальным. Для обновления базы введите команду update-database . В папке Migrations будет вестись история ваших миграций и вы в любой момент сможете откатить базу данных к любому этапу, используя команду update-database с именем миграции до которой нужно произвести откат изменений. Например последняя миграция у нас test_002 а нам нужно откатить до версии test_001, для этого мы должны ввести команду: update-database test_001
Думаю на этом этапе с миграциями мы закончим, если что-то непонятно по миграциям пишите в комментариях. Далее рассмотрим непосредственно работу с базой.
Работа с базой данных
Сохранение
Для того чтобы добавить данные о персонаже в базу, нам нужно создать экземпляр нашего класса и добавить его в контекст при помощи метода Add(), после чего нужно сохранить все изменения из контекста данных непосредственно в базу при помощи метода SaveChanges()
public void OnRegistration(Client client, string name, string lastname, string password) { //не забываем про хеширование пароля перед сохранением в бд //создаем нового персонажа Character Char = new Character { Social = client.SocialClubName, Name = name, Lasname = lastname, Password = password, Finance = new Finances(), State = new States(), Inventory = new List<Item>(), Date = DateTime.Now }; //добавляем его в контекст данных Db.Instance.Add(Char); //сохранянем изменения в базе данных Db.Instance.SaveChanges(); }
Для обновления данных нужно воспользоваться методом Update() для обновления данных о персонаже, и так же зафиксировать их при помощи метода SaveChanges()
//обновляем данные в контексте Db.Instance.Update(Char); //и сохраняем в бд Db.Instance.SaveChanges();
Загрузка
С загрузкой дела немного обстоят по другому. Для начала нам не нужны данные находящиеся в другой таблице, будь то состояние персонажа в нашем примере, его кастомизация или что-то еще. Нам будет достаточно информации о его логине и пароле. Рассмотрим пример загрузки данных из бд:
public void OnRegistration(Client client, string pwd) { //Получаем персонажа из бд Character Char = Db.Instance.Characters.SingleOrDefault(c=>c.Social == client.SocialClubName); //если записи соответствующей кретерию нашего запроса нет вернется Null if (Char == null) return; //проверяем пароль на совпадение (не забываем про хеш) if (Char.Password == pwd) { //подгружаем зависимые классы вынексеные в отдельную таблицу Db.Instance.Entry(Char).Reference(c => c.State).Load(); //создаем ссылку на нашу модель игрока client.SetData("Character", Char); //загружаем игрока //.............. } else { //если не прошел проверку отправляем на повторный логин //................ } }
В этом методе, в первую очередь, мы получаем первое значение соответствующее критерию нашего запроса и возвращаем экземпляр объекта Character со свойствами взятыми из бд. Свойство State, хранящееся в отдельно таблице, будет иметь значение null,его нужно будет явно запросить из базы, но на данном этапе нам достаточно данных чтобы сверить полученный от клиента пароль с паролем из бд (не забывайте про шифрование паролей). Если ни одна одна запись не будет соответствовать критерию нашего запроса вернется Null, это скажет нам о том что пользователя с данным логином не существует.
Если значение пароля совпадает то пришло время подгрузить недостающие данные. Делаем это мы при помощи метода Load() для необходимого свойства - в нашем случае это State
Db.Instance.Entry(Char).Reference(c => c.State).Load();
На этом этапе наш класс загружен в полном объеме и готов к употреблению. Нам осталось сохранить ссылку на него что бы в дальнейшем можно было манипулировать данными.
На этом думаю закончу, если что-то непонятно пишите, постараюсь дополнить. А я устал - я ухожу...
-
6
-
1
-
#
-
Спрятать интерфейс можно функциями из этого раздела:
https://wiki.rage.mp/index.php?title=Ui::displayHud
Для отрисовки своего интерфейса используй событие render:
-
3
-
-
Если актуально:
Оградить игроков при помощи свойства dimension :
https://wiki.rage.mp/index.php?title=Entity::dimension
Интерьеры некоторые нуждаются в загрузке:
https://wiki.rage.mp/index.php?title=Interiors_and_Locations
-
2
-











[TUTORIAL] Entity Framework Core (Postgresql)
in Tutorials
Posted · Edited by Malboro
На работе у меня часто бывает время для занятия какой-то херней (а хули "совок") и я могу иногда потратить его на что-то полезное. Предлагайте темы(С#, HTML, CSS, JS, Vue, php...)