Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/15: Рейтинг темы: голосов - 15, средняя оценка - 4.87
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1

Создание модели данных или нет

24.05.2018, 11:43. Показов 2936. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Допустим есть довольно сложная программа работающая с десятками таблицами из базы данных. Вот она создана с помощью встроенных конструкторов - путем добавления DataSet (пример на скрине) в виде файла xsd. И запросы и хранимые процедуры обрабатываюся там же в конструкторах. И в этом приложении нет отдельной модели данных в виде библиотеки dll. Вот такой подход к создание сложного приложения какой на ваш взгляд? Или все таки нужно создать модель данных без встроенных конструкторов?
Миниатюры
Создание модели данных или нет  
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
24.05.2018, 11:43
Ответы с готовыми решениями:

Создание библиотеки классов модели данных сущностей ADO.NET
Я создал при помощи Visual studio community 2015( localdb) базу данных books.mdf. Далее чтобы работать с ней создаю библиотеку классов...

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

Создание базы данных на лету, создание и заполнение таблиц в базе DB (Paradox? или..).
Здравствуйте Профи! --- Видел я "простенькую" (exe-шник небольшого размера, запускается сразу, без предварительной установки)...

23
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
24.05.2018, 11:45  [ТС]
Просто интересно ваше мнение.
0
Эксперт .NET
 Аватар для Usaga
14303 / 9388 / 1354
Регистрация: 21.01.2016
Сообщений: 35,398
24.05.2018, 11:48
aleksskay4, правильно было бы наделать моделей под каждую таблицу и отдельные виды запросов и положить их в отдельную сборку, которую могут другие части приложения переиспользовать (потенциально).

И под моделями я понимаю не DataSet-ы, а нормальные классы.
0
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
24.05.2018, 11:52  [ТС]
На примере можно показать?
0
Эксперт .NET
 Аватар для Usaga
14303 / 9388 / 1354
Регистрация: 21.01.2016
Сообщений: 35,398
24.05.2018, 11:57
aleksskay4, я не уверен, что тут пример нужен. Классы создавать же умеете? Сборки? Вот и всё)

Классы должны представлять отражения таблиц. Так же могут быть классы-DTO, которые представляют результаты запросов (какие-то подмножества полей таблицы). Вот и вся магия.
0
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
24.05.2018, 12:15  [ТС]
Вот когда я создавал приложение там была таблица со столбцами id, question, first, second, third, forth, right я для него создал такой класс:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Tests// Данный класс предназначен             //для считывания тестов из базы данных
    {          
        OleDbCommand com; 
        OleDbDataReader reader; // объект позволяет 
                                 //считывать данные из базы данных
        public int NumberQuestion { get; set; } // номер вопроса
        public string Question { get; set; }// содержит вопрос 
        public string First { get; set; }   //содержит первый вариант
        public string Second { get; set; }  //содержит второй вариант
        public string Third { get; set; }   //содержит третий вариант
        public string Forth { get; set; }   //содержит четвертый вариант
        public string Right { get; set; }   //содержит верный вариант
               
        
        public Tests(OleDbConnection con, string Query)
        {   // конструктор класса 
            //con - объект  типа Connection
            // Query - это sql-запрос
            NumberQuestion = 0;
            com = con.CreateCommand();
            com.CommandText = Query;
            reader = com.ExecuteReader();
        }
 
        public void ShowVariants( )
        {
            if (reader.Read()) // Считываем данные из таблицы Tests
            {
                Question = reader["Question"].ToString();
                First = reader["First"].ToString();
                Second = reader["Second"].ToString();
                Third = reader["Third"].ToString();
                Forth = reader["Forth"].ToString();
                Right = reader["Right"].ToString();
                NumberQuestion += 1;
            }
        }
 
        public void CloseTests()
        {
            reader.Close();
        }
        
    }
Потом в коде использовал
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
 if (fmBegin.Subject == "Информатика")
                test = new Tests(fmLogin.con, " SELECT * FROM  Information ");
            else test = new Tests(fmLogin.con, " SELECT * FROM  Programming ");
            SelTest();      // Заносим вопрос и варианты в radioButton
        private void SelTest()
        {
            test.ShowVariants();
            laQuestion.Text = test.NumberQuestion + ") " + test.Question;
            rbFirst.Text = test.First;
            rbSecond.Text = test.Second;
            rbThird.Text = test.Third;
            rbForth.Text = test.Forth;
        }
Так правильно?
0
360 / 287 / 76
Регистрация: 21.06.2016
Сообщений: 1,115
24.05.2018, 12:15
aleksskay4, ответ очень даже простой в этом случае. Модель создавать НУЖНО, даже если это не самая сложная программа. Это даст Вам много вкусняшек, из них можно выделить:
1. Создание нового объекта в памяти проще и быстрее, чем в СУБД, к тому же таблицы не портятся моментами создания записей и (потенциально) не будет проблем с автоинкрементами.
2. При сохранении объекта - это будет единовременная операция, и в случае многопользовательского режима можно установить блокировку через транзакцию. Особенно удобно при построении деревьев с их структурой parent-child.
3. При удалении объекта без сохранения - снова же не нужно дергать сиквел (а часто пользователи такими вещами пользуются, создали объект, а потом - не, не хочу, хочу другой - и отменили без сохранения).
4. Отделяете хранилище данных от Ваших форм, можно менять формы на ходу, не задумываясь о состоянии данных внутри, а работать с байндингами динамически.
5. Модель данных, при правильном проектировании не зависит от типов используемых СУБД, достаточно прописать различные реализации интерфейса для работы с разными СУБД.
6. Возможность менять даже технологию (WPF/WinForms) - а модель останется та же.
Да и еще можно с десяток-другой вкусняшек написать. Это только то, что сразу в голову пришло.
И да, модель - это не набор датасетов, а набор классов, в которых могут содержаться и датасеты тоже.
1
Эксперт .NET
 Аватар для Usaga
14303 / 9388 / 1354
Регистрация: 21.01.2016
Сообщений: 35,398
24.05.2018, 13:03
aleksskay4, ваш пример страшно кривой. Это не модель - это какой-то класс-самозагружатор. Вариация на тему Active Record.

Под моделями данных понимаются обычные POCO (Plain Old CLR Object). Т.е. классы со свойствами без всякого (или с минимальным) поведения. Т.е. просто мешок с данными и всё.

По такому классу не должно быть видно откуда в него данные попали, из базы или ещё откуда. Такой класс можно вообще везде переиспользовать: в консоли, в вебе, ещё где, в связке с СУБД MySQL или из MongoDB.

Ваш же прибит гвоздями к OleDbConnection. Это уже не модель. Это уже некий сервис-мутант.
2
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
24.05.2018, 13:39  [ТС]
C#
1
2
3
4
5
6
7
8
9
10
 class Tests
    {
        public int NumberQuestion { get; set; } // номер вопроса
        public string Question { get; set; }// содержит вопрос 
        public string First { get; set; }   //содержит первый вариант
        public string Second { get; set; }  //содержит второй вариант
        public string Third { get; set; }   //содержит третий вариант
        public string Forth { get; set; }   //содержит четвертый вариант
        public string Right { get; set; }   //содержит верный вариант
    }
Такой? Если да то как его правильно использовать?
0
Эксперт .NET
 Аватар для Usaga
14303 / 9388 / 1354
Регистрация: 21.01.2016
Сообщений: 35,398
24.05.2018, 13:42
aleksskay4, да, такой. Просто набор свойств.

Цитата Сообщение от aleksskay4 Посмотреть сообщение
как его правильно использовать?
Это вопрос в контексте работы с базой данных? Если да, то нужно результаты запросов выгружать в подобные классы и работать уже с ними. И наоборот: если что-то сохранить надо, то параметры для запросов брать из классов (если речь не про отдельный какой-нибудь параметр, где наличие класса избыточно).
0
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
24.05.2018, 14:47  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
Если да, то нужно результаты запросов выгружать в подобные классы и работать уже с ними.
Как выгружать? Так :
C#
1
List<Tests> tests = new  List<Tests>();
Потом выгружать в этот список результат запроса?
0
Эксперт .NET
 Аватар для Usaga
14303 / 9388 / 1354
Регистрация: 21.01.2016
Сообщений: 35,398
24.05.2018, 17:02
aleksskay4, ну типа. Вы можете это сделать вручную, можете воспользоваться такими классными штуками как PetaPoco и Dapper или вообще "взрослыми" ORM типа LINQtoDB и Entity Framework.
0
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
25.05.2018, 16:22  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
Ваш же прибит гвоздями к OleDbConnection. Это уже не модель
Допустим если известно что постоянно будет использоваться один сервер например SQL Server модель нельзя использовать поставщики? Такая модель и для другого WinForms, Wpf приложения подходит. Надеюсь несколько человек прокомментирует.
Когда я писал что-то вроде мессенджер я создал такой класс ? Она не подходит под модель? И как такой способ создание приложений(ваша оценка такому способу) ?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Data.SqlClient;
using System.Data;
using System.Windows.Forms;
using System.Drawing;
using System.Data.Common;
 
namespace ConnectionDLL
{
    public class ConnectionData :IConnection
    {
        private SqlConnection connection;
 
        private SqlDataAdapter adapter;
 
        private DataSet dataSet;
 
        public List<string> TableNames { get; set; }
 
        public DataTable DisplayNames { get; set; }
 
        public List<string> Names { get; set; }
     
 
        // первый конструктор, вызывается при входе в Connection
        public ConnectionData (string conString, string userLogin)
        {
            this.OpenConnection(conString);
            SqlCommand com = new SqlCommand("GetNames", connection);
            com.CommandType = CommandType.StoredProcedure;
            userLogin = this.ModifyName(userLogin);
            com.Parameters.AddWithValue("@userLogin", userLogin);
            com.ExecuteNonQuery();
            DataTable Names = new DataTable();
            adapter = new SqlDataAdapter(com);
            adapter.Fill(Names);             
            this.DisplayNames = Names;
 
            List<string> list = new List<string>();
 
            com = new SqlCommand("select * from dbo.GetTables()", connection);
            com.CommandType = CommandType.Text;
            Names = new DataTable();
            adapter = new SqlDataAdapter(com);
            adapter.Fill(Names);
            foreach(DataRow row in Names.Rows)
            {
                list.Add(row["TableName"].ToString());
            }
            this.TableNames = list;
            com.Dispose();
        }
 
        // Вторая форма конструктора
        // Вызывается при регистрация нового пользователя.
        public ConnectionData (string ConnectionString)
        {
            this.OpenConnection(ConnectionString);
            List<string> list = new List<string>();
            SqlCommand com;
            com = new SqlCommand("GetNamesLogins", connection);
            com.CommandType = CommandType.StoredProcedure;
            DataTable Names;
            Names = new DataTable();
            adapter = new SqlDataAdapter(com);
            adapter.Fill(Names);
            foreach (DataRow row in Names.Rows)
            {
                list.Add(row["UserLogin"].ToString());
            }
            this.Names = list;
        }
 
        // Открытие соединения с базой FirstBas
        public bool OpenConnection(string ConString)
        {
            connection = new SqlConnection(ConString);
            try
            {
                connection.Open();                
            }
            
            catch(Exception exp)
            {
                   MessageBox.Show(exp.Message, "Ошибка соединения с базой данных");
               return false;
            }
            return true;
 
        }
 
        // выбираем сообщения из таблицы
        public DataSet SelData (string sql1)
        {
            try
            {
                SqlCommand com = new SqlCommand(sql1, connection);
                adapter = new SqlDataAdapter(com);
                dataSet = new DataSet();
                adapter.Fill(dataSet, "firstTable");
                
            }
 
            catch (SqlException exp)
            {
                MessageBox.Show(exp.Message, "Ошибка");
            }     
            return dataSet;           
            
        }
 
        // В richTextBox будут показаны сообщения 
        //Iuser -это тот кто за компом пишет.
        //remoteUser - удаленный пользователь, который вам отвечает.
        //  
        public void GetMessages (RichTextBox richTextBox, string Iuser, string remoteUser)
        {            
 
            foreach (DataRow row in dataSet.Tables[0].Rows)
            {
               
                if (row["Users"].ToString() == Iuser)
                {
                    richTextBox.SelectionAlignment = HorizontalAlignment.Right;
                    richTextBox.AppendText(row["UserText"].ToString() + "\r\n" + "\r\n");
                }
                if (row["Users"].ToString() == remoteUser)
                {
                    richTextBox.SelectionAlignment = HorizontalAlignment.Left;
                    richTextBox.AppendText(row["UserText"].ToString() + "\r\n" + "\r\n");
                }            
            }            
        }
 
        // Получение имен для выбора в lbUser
        
 
        public void SendMessage(string nameProc,  string UserText,
            string iUser )
        {
            SqlCommand com = new SqlCommand();
            com.Connection = connection;
            com.CommandType = CommandType.StoredProcedure;
            com.CommandText = "INS_" + nameProc;
            com.Parameters.AddWithValue("@Users", iUser);
            com.Parameters.AddWithValue("@UserText", UserText);
            com.ExecuteNonQuery();
        }
 
        // Добавление данные в таблицу Logins
        public void AddLogins( string photoFilePath )
        {
            byte[] photo = GetPhoto(photoFilePath);
            SqlCommand com = new SqlCommand();
            com.Connection = connection;
            com.CommandText = "";
        }
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
25.05.2018, 16:43
Цитата Сообщение от aleksskay4 Посмотреть сообщение
Она не подходит под модель?
Нет, не подходит.
aleksskay4, вам ведь уже сказали, что модели, в общем случае, отображаются на таблицы.
И это просто POCO, они не должны иметь способность сами себя загружать из бд. За загрузку данных извне отвечает абстрактный слой - репозиторий.
Модель ни от чего не зависит, на то она и модель. Если вы смените используемую СУБД, то это никак не должно затрагивать модель. От этого и исходите.
2
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
25.05.2018, 17:44  [ТС]
В плане репозитария наверно имеются в ввиду так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface IDoorRepository
    {
        IQueryable<Door> Doors { get; }
        IQueryable<Land> Lands { get; }
        IQueryable<Armchair> Armchairs { get; }
        IQueryable<Table> Tables { get; }
 
        void SaveLand(Land land);
        void SaveDoor(Door door);
        void SaveArmchair(Armchair armchair);
        void SaveTable(Table table);
        Door DeleteDoor(int DoorId);
        Land DeleteLand(int LandId);
        Armchair DeleteArmchair(int ArmchairId);
        Table DeleteTable(int TableId);
    }
Ну и так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class EFDoorRepository : IDoorRepository
    {
        private EFDbContext context = new EFDbContext();
 
        public IQueryable<Door> Doors
        {
            get { return context.Doors; }
        }
 
        public IQueryable<Land> Lands
        {
            get { return context.Lands; }
        }
 
        public IQueryable<Armchair> Armchairs
        {
            get { return context.Armchairs; }
        }
 
        public IQueryable<Table> Tables
        {
            get { return context.Tables; }
        }
 
        // Сохраняем изменения в таблице Doors
        public void SaveDoor(Door door)
        {
            if (door.DoorId == 0)
            {
                context.Doors.Add(door);
            }
            else
            {
                Door dbEntry = context.Doors.Find(door.DoorId);
                if (dbEntry != null)
                {
                    dbEntry.TypeDoor = door.TypeDoor;
                    dbEntry.Tree = door.Tree;
                    dbEntry.Price = door.Price;
                    dbEntry.ImageData = door.ImageData;
                    dbEntry.ImageMimeType = door.ImageMimeType;
                }
            }
            context.SaveChanges();
        }
 
        // Удаляем запись из таблицы Doors
        public Door DeleteDoor(int DoorId)
        {
            Door dbEntry = context.Doors.Find(DoorId);
            if (dbEntry != null)
            {
                context.Doors.Remove(dbEntry);
                context.SaveChanges();
            }
            return dbEntry;
        }
 
        // Сохраняем изменения в таблице Land.
        public void SaveLand(Land land)
        {
            if (land.LandId == 0)
            {
                context.Lands.Add(land);
            }
            else
            {
                Land dbEntry = context.Lands.Find(land.LandId);
                if (dbEntry != null)
                {
                    dbEntry.TypeOfLand = land.TypeOfLand;
                    dbEntry.Tree = land.Tree;
                    dbEntry.Price = land.Price;
                    dbEntry.ImageData = land.ImageData;
                    dbEntry.ImageMimeType = land.ImageMimeType;
                }                
            }
            context.SaveChanges();
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 public class Door
    {   
        [HiddenInput(DisplayValue = false)]
        public int DoorId { get; set; }
        [Required(ErrorMessage ="Пожалуйста, введите тип двери")]
        public string TypeDoor { get; set; }
        [Required(ErrorMessage ="Пожалуйста, введите вид дерево")]
        public string Tree { get; set; }
        [Range(0.01, double.MaxValue, ErrorMessage ="Пожалуйста, введите корректную сумму. ")]
        public decimal Price { get; set; }
 
        public byte[] ImageData { get; set; }
        [HiddenInput(DisplayValue = false)] 
        public string ImageMimeType { get; set; }
    }
Это когда под asp.net mvc писал. Наверно так должно быть, да?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
25.05.2018, 19:03
aleksskay4, уже лучше. Но у вас в одном репо по сути две штуки - для кресел и для дверей.
Читали про interface segregation principle?
0
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
25.05.2018, 21:58  [ТС]
IamRain, А что нужно сделать?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
25.05.2018, 22:02
На каждую сущность отдельный репозиторий.
Обычно создают интерфейс для одной сущности и одну дефолтную реализацию.
0
 Аватар для aleksskay4
71 / 68 / 46
Регистрация: 02.12.2015
Сообщений: 891
Записей в блоге: 1
25.05.2018, 22:10  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
На каждую сущность отдельный репозиторий.
То есть нужно создать отдельный интерфейс например IArmchairRepository?
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
25.05.2018, 22:13
Да, вот здесь есть мат.часть.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.05.2018, 22:13
Помогаю со студенческими работами здесь

Включать или нет базу данных в проект?
Здравствуйте! В первой форме была подключена база данных, я ее включила в проект. В проекте получилось три базы данных: в основной папке и...

Проверка занят или нет ник в базе данных
private void button1_Click(object sender, EventArgs e) { string name = textBox1.Text; string parol...

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

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

Создание инфологической модели базы данных
Начал писать документацию к дипломной работе, есть 2 пункта: Концептуальное проектирование базы данных; Инфологическое проектирование...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru