powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Реализация отношения много-ко-многим.
20 сообщений из 20, страница 1 из 1
Реализация отношения много-ко-многим.
    #39222106
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Моделируем сущности на основе БД:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
    class Client
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int EGN { get; set; }
        public DateTime Birthday { get; set; }

        public ICollection<Company> Companies { get; set; }
    }

    class Company
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Location { get; set; }

        public ICollection<Client> Clients { get; set; }
    }



Была идея так же создать третий класс к которому ведут эти таблицы, который выглядит следующим образом, но предподаватель сказал, что в нём нет необходимости.
Код: c#
1.
2.
3.
4.
5.
6.
    class ClientCompany
    {
        public int ID { get; set; }
        public int ClientID { get; set; }
        public int CompanyID { get; set; }
    }


Задача. Вернуть список компаний с ихними клиентами, но если один человек евляеться клиентом двух компаний, то он должен быть представителем одного и того же объекта.
Начала с подобного:
Код: 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.
public ICollection<Company> GetClientCompany()
        {
            using (SqlConnection myConnection = new SqlConnection(connection.ConnectionString))
            {
                myConnection.Open();
                string strSQL = "SELECT ClientCompanies.ID, " +
                                       "Clients.FirstName, " +
                                       "Clients.LastName, " +
                                       "Company.Name " +
                                "FROM ClientCompanies " +
                                "INNER JOIN Clients ON Clients.ID = ClientCompanies.ClientID " +
                                "INNER JOIN Company ON Company.ID = ClientCompanies.CompanyID " +
                                "ORDER BY Clients.ID";

                using (SqlCommand myCommand = new SqlCommand(strSQL, myConnection))
                {
                    using (SqlDataReader reader = myCommand.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
                    {
                        Dictionary<int, Client> clients = new Dictionary<int, Client>();
                        Dictionary<int, Company> companies = new Dictionary<int, Company>();
                        while (reader.Read())
                        {
                            Client client = new Client();
                            client.FirstName = Convert.ToString(reader["FirstName"]);
                            client.LastName = Convert.ToString(reader["LastName"]);
                            client.Companies = new List<Company>();

                            Company company = new Company();
                            company.Name = Convert.ToString(reader["Name"]);
                            company.Clients = new List<Client>();
                                                        
                            Client existingClient = null;
                            Company existingCompany = null;
                            
                        }

                        return companies.Values;
                    }
                }
            }
        }


LINQ пользоваться запретили, и заявка к БД должна быть только одна.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39222111
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Извините, по ошибке создал тему в этой ветки, а не в соседней, если можно перенесите. И пожалуйста исправьте евляеться, на является, а то я не вижу возможности редактировать сообщение, не доспал глупые ошибки, простите.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39222949
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafe,

Ну так у тебя ж каждый клиент имеет свой уникальный ID. Просто перед вставкой в общий список клиентов проверяй наличие єлемента с такам же ID, и не вставляй его. Ну а для компаний сохрани связку ID компании <-> ID клиента (можно в классе Company сделать отдельный список клиентов только этой компании). Тогда по ID клиента можно брать элемент из общего списка клиентов (одна и та же сущность).

P.S. Лучше сделать ORDER BY по id компании.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223182
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Оставлю здесь, как я решил данную проблему. Только модераторы перенесите пожалуйста тему. Это всё таки ADO.net
Код: 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.
        public ICollection<Company> GetClientCompany()
        {
            using (SqlConnection myConnection = new SqlConnection(connection.ConnectionString))
            {
                myConnection.Open();
                string strSQL = "SELECT ClientCompanies.ID, " +
                                       "Clients.ID AS ClientID, " +
                                       "Clients.FirstName, " +
                                       "Clients.LastName, " +
                                       "Company.ID AS CompanyID, " +
                                       "Company.Name " +
                                "FROM ClientCompanies " +
                                "INNER JOIN Clients ON Clients.ID = ClientCompanies.ClientID " +
                                "INNER JOIN Company ON Company.ID = ClientCompanies.CompanyID " +
                                "ORDER BY Clients.ID";

                using (SqlCommand myCommand = new SqlCommand(strSQL, myConnection))
                {
                    using (SqlDataReader reader = myCommand.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
                    {
                        Dictionary<int, Company> companies = new Dictionary<int, Company>();
                        Dictionary<int, Client> clients = new Dictionary<int, Client>();
                        while (reader.Read())
                        {
                            Client client = new Client();
                            client.ID = Convert.ToInt32(reader["ClientID"]);
                            client.FirstName = Convert.ToString(reader["FirstName"]);
                            client.LastName = Convert.ToString(reader["LastName"]);
                            client.Companies = new List<Company>();

                            Company company = new Company();
                            company.ID = Convert.ToInt32(reader["CompanyID"]);
                            company.Name = Convert.ToString(reader["Name"]);
                            company.Clients = new List<Client>();
                                                        
                            
                            Client existingClient = null;
                            if (!clients.TryGetValue(client.ID, out existingClient)) // client don't exist
                            {
                                clients.Add(client.ID, client);
                                company.Clients.Add(client);
                            }
                            else
                            {
                                clients[client.ID].Companies.Add(company);
                                company.Clients.Add(existingClient);
                            }

                            Company existingCompany = null;
                            if (!companies.TryGetValue(company.ID, out existingCompany)) // company don't exist
                            {
                                companies.Add(company.ID, company);
                                client.Companies.Add(company);
                            }
                            else
                            {
                                client.Companies.Add(existingCompany);
                                companies[company.ID].Clients.Add(client);
                            }
                        }

                        return companies.Values;
                    }
                }
            }
        }
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223228
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafeLINQ пользоваться запретили, и заявка к БД должна быть только одна.

LINQ запретили, запрос - это "заявка", это что за колхоз?
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223286
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafe, вместо TryGetValue используйте метод ContainsKey для проверки существования элемента в словаре.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223308
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MonochromatiqueunsafeLINQ пользоваться запретили, и заявка к БД должна быть только одна.

LINQ запретили, запрос - это "заявка", это что за колхоз?
Я думаю программист должен знать как выполнить эту задачу без использования LINQ. LINQ сильно упрощает жизнь. К тому же, с точки зрения оптимизации лучше обычный SQL запрос.
skyANA, С TryGetValue мы так же присваиваем значение, которое будет в последствие использоваться. Если клиент/компания существует, то переменной existingClient/existingCompany будет присвоено существующее значение из словаря. А ContainsKey вернёт лишь булевое значение.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223314
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafeskyANA, С TryGetValue мы так же присваиваем значение, которое будет в последствие использоваться. Если клиент/компания существует, то переменной existingClient/existingCompany будет присвоено существующее значение из словаря. А ContainsKey вернёт лишь булевое значение.
Тогда объясните зачем выделенный ниже фрагмент кода:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
if (!clients.TryGetValue(client.ID, out existingClient)) // client don't exist
{
    clients.Add(client.ID, client);
    company.Clients.Add(client);
}
else
{
    clients[client.ID].Companies.Add(company);
    company.Clients.Add(existingClient);
}


И кстати Вы дублируете company.Clients.Add в ветках if-а.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223317
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И ещё у Вас сплошные баги. Вы сначала найдите и клиента и компанию, или создайте новые, если их нет в словарях, а потом уже связывайте друг с другом.

Код: 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.
Client client = null;
Company company = null;

var clientID = Convert.ToInt32(reader["ClientID"]);
var companyID = Convert.ToInt32(reader["CompanyID"]);

if (!clients.TryGetValue(clientID, out client))
{
    client = new Client();
    client.ID = clientID;
    client.FirstName = Convert.ToString(reader["FirstName"]);
    client.LastName = Convert.ToString(reader["LastName"]);
    client.Companies = new List<Company>();

    clients.Add(clientID, client);
}

if (!companies.TryGetValue(companyID, out company))
{
    company = new Company();
    company.ID = companyID;
    company.Name = Convert.ToString(reader["Name"]);
    company.Clients = new List<Client>();
   
    companies.Add(companyID, company);
}                                                        

client.Companies.Add(company);                            
company.Clients.Add(client);
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223454
Monochromatique
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafeЯ думаю программист должен знать как выполнить эту задачу без использования LINQ.

Особенно - используя "в заявке" таблицу, которую сгенерил EF.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223485
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
skyANAunsafeskyANA, С TryGetValue мы так же присваиваем значение, которое будет в последствие использоваться. Если клиент/компания существует, то переменной existingClient/existingCompany будет присвоено существующее значение из словаря. А ContainsKey вернёт лишь булевое значение.
Тогда объясните зачем выделенный ниже фрагмент кода:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
if (!clients.TryGetValue(client.ID, out existingClient)) // client don't exist
{
    clients.Add(client.ID, client);
    company.Clients.Add(client);
}
else
{
    clients[client.ID].Companies.Add(company);
    company.Clients.Add(existingClient);
}



Добавление компании к уже существующему клиенту
skyANAИ кстати Вы дублируете company.Clients.Add в ветках if-а.
Да, но в случае когда клиента не существует добавляется клиент который был считан из БД, когда же клиент существует, он добавляется в словарь к уже существующей компании.
skyANAИ ещё у Вас сплошные баги. Вы сначала найдите и клиента и компанию, или создайте новые, если их нет в словарях, а потом уже связывайте друг с другом.
В чём именно заключаются баги? Разница лишь в том что в моей реализации сначала считываются все данные, а потом уже проверяется существует ли такой клиент/компания. Скорее это не баг, а не рациональное использовании ресурсов. Ваша реализация гораздо боле практичная. Спасибо.
MonochromatiqueОсобенно - используя "в заявке" таблицу, которую сгенерил EF.
Нет. Написал сам вручную. Если сгенерил EF где же тогда модификатор virtual перед коллекцией?
Сейчас додумываю, что надо было мне ещё знак вопроса ставить после типов которые принимают null в БД. Ну и соответственно проверка на DBNull при извлечении данных из БД
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39223523
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafeskyANAпропущено...

Тогда объясните зачем выделенный ниже фрагмент кода:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
if (!clients.TryGetValue(client.ID, out existingClient)) // client don't exist
{
    clients.Add(client.ID, client);
    company.Clients.Add(client);
}
else
{
    clients[client.ID].Companies.Add(company);
    company.Clients.Add(existingClient);
}



Добавление компании к уже существующему клиентуЯ же Вам чётко выделил фрагмент: clients[client.ID] , - этот код ничего никуда не добавляет, он достаёт из словаря значение по ключу.
Зачем, если Вы уже достали его методом TryGetValue ?

unsafeskyANAИ кстати Вы дублируете company.Clients.Add в ветках if-а.
Да, но в случае когда клиента не существует добавляется клиент который был считан из БД, когда же клиент существует, он добавляется в словарь к уже существующей компании.Я прекрасно понял, что должен делать Ваш код, намекаю на то, что его можно упростить :)

unsafeskyANAИ ещё у Вас сплошные баги. Вы сначала найдите и клиента и компанию, или создайте новые, если их нет в словарях, а потом уже связывайте друг с другом.
В чём именно заключаются баги? Разница лишь в том что в моей реализации сначала считываются все данные, а потом уже проверяется существует ли такой клиент/компания. Скорее это не баг, а не рациональное использовании ресурсов. Ваша реализация гораздо боле практичная. Спасибо.Вы бы для начала внимательно посмотрели на свой код, а потом уже утверждали, что "Разница лишь в том.." :)

Рассмотрим случай, когда и клиент и компания уже существуют в словарях. НЕ существующими я буду называть объекты, что созданы через new, а не найдены в словаре.
Что делает Ваш код?

1.
Код: c#
1.
2.
clients[client.ID].Companies.Add(company);
company.Clients.Add(existingClient);


Существующему клиенту, добавляет ссылку на НЕ существующую компанию, а ей зачем-то добавляет ссылку на существующего клиента.

2.
Код: c#
1.
2.
client.Companies.Add(existingCompany);
companies[company.ID].Clients.Add(client);


НЕ существующему клиенту добавляется ссылка на существующую компанию, а потом ей же добавляется ссылка на НЕ существующего клиента.

В результате задание не выполнено.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39225315
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
skyANA, После вашей реализации пытаюсь заново взглянуть на свой криворукий код. Можете глянуть, пожалуйста
Сущность:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public int CategoryID { get; set; }

        public Category Category { get; set; }
        public List<Order> Order { get; set; }
    }




Функция:
Код: 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.
        public ICollection<Product> GetProductJoinCategogiesAndOrders()
        {
            using (SqlConnection myConnection = new SqlConnection(connection.ConnectionString))
            {
                myConnection.Open();
                string strSQL = "SELECT Products.ID AS ProductID, " +
                                       "Products.Name AS ProductName, " +
                                       "Products.Price, " +
                                       "Orders.ID AS OrderID, " +
                                       "Orders.Quentity, " +
                                       "Categories.Name AS CategoryName " +
                                "FROM Products " +
                                "INNER JOIN Categories ON Categories.ID = Products.CategoryID " +
                                "LEFT JOIN Orders ON Orders.ProductID = Products.ID " +
                                "ORDER BY Products.ID";

                using (SqlCommand myCommand = new SqlCommand(strSQL, myConnection))
                {
                    using (SqlDataReader reader = myCommand.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
                    {
                        Dictionary<int, Product> products = new Dictionary<int, Product>();

                        while (reader.Read())
                        {

                            Product product = null;
                            int productID = Convert.ToInt32(reader["ProductID"]);

                            if (!products.TryGetValue(productID, out product))
                            {
                                product = new Product();
                                product.ID = productID;
                                product.Name = reader.IsDBNull(1) ? "Product without name" : Convert.ToString(reader["ProductName"]);
                                product.Price = Convert.ToDecimal(reader["Price"]);

                                product.Category = new Category();
                                product.Category.Name = reader.IsDBNull(5) ? "Category without name" : Convert.ToString(reader["CategoryName"]);
                                
                                products.Add(productID, product);
                            }

                            product.Order = new List<Order>();
                            Order o = new Order();
                            o.ID = reader.IsDBNull(3) ? 0 : Convert.ToInt32(reader["OrderID"]);
                            o.Quentity = reader.IsDBNull(4) ? 0 : Convert.ToInt32(reader["Quentity"]);

                            products[productID].Order.Add(o);
                        }

                        return products.Values;
                    }
                }
            }


Где соотношение продуктов с категориями это 1-к-1, соотношение категорий с заказами это 1-ко-многим. Что то со списком заказов мне как то не очнеь нравиться, но при этом заказ будет каждую итерацию, то есть добавлять мы его к списку продуктов должны каждый раз. Правильно ли я это реализовал?
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39225325
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafe, подробно сформулируйте поставленную задачу. А то у меня большой вопрос о том, зачем в продукте держать список заказов.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39225327
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В реальной жизни как правило в заказ можно добавить несколько продуктов, а не только один.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39225449
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
skyANA, В данном случае, мы держим в продукте список всех заказов, а потом суммируем их кол-во и берём цену продукта, и получаем общую сумму заказов по конкретному продукту.
У нас экспериментальная база, полигон. Дают задание надо выполнить
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39226088
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafeskyANA, В данном случае, мы держим в продукте список всех заказов, а потом суммируем их кол-во и берём цену продукта, и получаем общую сумму заказов по конкретному продукту.
Держать в продукте список заказов только для того, чтобы их проссумировать - интересный эксперимент :)
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39226143
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
skyANA, =) Ну хоть правильно реализовал? Я имею ввиду код функции
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39226293
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unsafeskyANA, =) Ну хоть правильно реализовал? Я имею ввиду код функции
Нет, с ошибкой. Плохо тестируете.
...
Рейтинг: 0 / 0
Реализация отношения много-ко-многим.
    #39226558
unsafe
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
skyANA, Ужас, Вы меня один раз исправили, а я наступаю на те же грабли.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
                            Product product = null;
                            int productID = Convert.ToInt32(reader["ProductID"]);

                            if (!products.TryGetValue(productID, out product))
                            {
                                product = new Product();
                                product.ID = productID;
                                product.Name = reader.IsDBNull(1) ? "Product without name" : Convert.ToString(reader["ProductName"]);
                                product.Price = Convert.ToDecimal(reader["Price"]);

                                product.Category = new Category();
                                product.Category.Name = reader.IsDBNull(5) ? "Category without name" : Convert.ToString(reader["CategoryName"]);
                                
                                product.Order = new List<Order>();

                                products.Add(productID, product);
                            }

                            Order order = new Order();
                            order.ID = reader.IsDBNull(3) ? 0 : Convert.ToInt32(reader["OrderID"]);
                            order.Quentity = reader.IsDBNull(4) ? 0 : Convert.ToInt32(reader["Quentity"]);
                            product.Order.Add(order);

...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Реализация отношения много-ко-многим.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]