Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Реализация отношения много-ко-многим. / 20 сообщений из 20, страница 1 из 1
22.04.2016, 10:09
    #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
22.04.2016, 10:13
    #39222111
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
Извините, по ошибке создал тему в этой ветки, а не в соседней, если можно перенесите. И пожалуйста исправьте евляеться, на является, а то я не вижу возможности редактировать сообщение, не доспал глупые ошибки, простите.
...
Рейтинг: 0 / 0
23.04.2016, 01:47
    #39222949
DarkMaster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
unsafe,

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

P.S. Лучше сделать ORDER BY по id компании.
...
Рейтинг: 0 / 0
23.04.2016, 20:19
    #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
23.04.2016, 21:56
    #39223228
Monochromatique
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
unsafeLINQ пользоваться запретили, и заявка к БД должна быть только одна.

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

LINQ запретили, запрос - это "заявка", это что за колхоз?
Я думаю программист должен знать как выполнить эту задачу без использования LINQ. LINQ сильно упрощает жизнь. К тому же, с точки зрения оптимизации лучше обычный SQL запрос.
skyANA, С TryGetValue мы так же присваиваем значение, которое будет в последствие использоваться. Если клиент/компания существует, то переменной existingClient/existingCompany будет присвоено существующее значение из словаря. А ContainsKey вернёт лишь булевое значение.
...
Рейтинг: 0 / 0
24.04.2016, 11:06
    #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
24.04.2016, 11:22
    #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
24.04.2016, 22:47
    #39223454
Monochromatique
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
unsafeЯ думаю программист должен знать как выполнить эту задачу без использования LINQ.

Особенно - используя "в заявке" таблицу, которую сгенерил EF.
...
Рейтинг: 0 / 0
25.04.2016, 01:31
    #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
25.04.2016, 08:19
    #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
27.04.2016, 10:16
    #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
27.04.2016, 10:22
    #39225325
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
unsafe, подробно сформулируйте поставленную задачу. А то у меня большой вопрос о том, зачем в продукте держать список заказов.
...
Рейтинг: 0 / 0
27.04.2016, 10:24
    #39225327
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
В реальной жизни как правило в заказ можно добавить несколько продуктов, а не только один.
...
Рейтинг: 0 / 0
27.04.2016, 11:46
    #39225449
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
skyANA, В данном случае, мы держим в продукте список всех заказов, а потом суммируем их кол-во и берём цену продукта, и получаем общую сумму заказов по конкретному продукту.
У нас экспериментальная база, полигон. Дают задание надо выполнить
...
Рейтинг: 0 / 0
27.04.2016, 19:19
    #39226088
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
unsafeskyANA, В данном случае, мы держим в продукте список всех заказов, а потом суммируем их кол-во и берём цену продукта, и получаем общую сумму заказов по конкретному продукту.
Держать в продукте список заказов только для того, чтобы их проссумировать - интересный эксперимент :)
...
Рейтинг: 0 / 0
27.04.2016, 21:01
    #39226143
unsafe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
skyANA, =) Ну хоть правильно реализовал? Я имею ввиду код функции
...
Рейтинг: 0 / 0
28.04.2016, 08:04
    #39226293
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация отношения много-ко-многим.
unsafeskyANA, =) Ну хоть правильно реализовал? Я имею ввиду код функции
Нет, с ошибкой. Плохо тестируете.
...
Рейтинг: 0 / 0
28.04.2016, 12:44
    #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
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Реализация отношения много-ко-многим. / 20 сообщений из 20, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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