Jump to content

Search the Community

Showing results for tags 'npgsql'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • RAGE Multiplayer
    • Announcements
    • Discussion
    • Suggestions
  • Scripting
    • Scripting
    • Resources
  • Community
    • Support
    • Servers
    • Media Gallery
  • Non-English
    • Русский - Russian
    • Français - French
    • Deutsch - German
    • Espanol - Spanish
    • Română - Romanian
    • Portuguesa - Portuguese
    • Polski - Polish

Categories

  • Scripts
  • Gamemodes
  • Libraries
  • Plugins
  • Maps
  • Tools

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Facebook


Youtube


Skype


Web


VK

Found 2 results

  1. Hello, I have a problem --> Link <-- using Npgsql; using GTANetworkAPI; using System.Collections.Generic; using System.Globalization; using System.Text; using System.Threading.Tasks; using System; namespace Npgsql { public class Main : Script { [Command("test")] public void Hello(Client client) { string conn_param = "Server=127.0.0.1;Port=5432;User Id=postgres;Password=**********;Database=postgresqlDB;"; NpgsqlConnection conn = new NpgsqlConnection(conn_param); NpgsqlCommand com = new NpgsqlCommand("SELECT * FROM players;", conn); conn.Open(); NpgsqlDataReader reader; reader = com.ExecuteReader(); while (reader.Read()) { try { string result = reader.GetString(1); client.SendChatMessage(result); } catch { } } conn.Close(); } } } I must say right away that he cannot find the library, I understand, the fact is that it is present. If you add the file System.Data.Common in the folder from which the server is started, another error will appear. --> Link <-- And add the file System.Threading.tasks.extensions in the folder, Nothing happens.
  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(); На этом этапе наш класс загружен в полном объеме и готов к употреблению. Нам осталось сохранить ссылку на него что бы в дальнейшем можно было манипулировать данными. На этом думаю закончу, если что-то непонятно пишите, постараюсь дополнить. А я устал - я ухожу...
×
×
  • Create New...