MSSQL.Command.Handler 1.4.6

dotnet add package MSSQL.Command.Handler --version 1.4.6
                    
NuGet\Install-Package MSSQL.Command.Handler -Version 1.4.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MSSQL.Command.Handler" Version="1.4.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MSSQL.Command.Handler" Version="1.4.6" />
                    
Directory.Packages.props
<PackageReference Include="MSSQL.Command.Handler" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MSSQL.Command.Handler --version 1.4.6
                    
#r "nuget: MSSQL.Command.Handler, 1.4.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MSSQL.Command.Handler@1.4.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MSSQL.Command.Handler&version=1.4.6
                    
Install as a Cake Addin
#tool nuget:?package=MSSQL.Command.Handler&version=1.4.6
                    
Install as a Cake Tool

MSSQL.Command.Handler

The MSSQL.Command.Handler is an advanced and highly efficient library meticulously designed to streamline the execution and management of SQL commands within Microsoft SQL Server environments. This comprehensive package offers an extensive array of tools and utilities, significantly simplifying the process of handling SQL commands and enabling developers to interact with their databases more effectively and with greater ease.

Key Features

Command Execution

The MSSQL.Command.Handler library provides an intuitive and straightforward API for executing SQL commands and stored procedures. This feature drastically reduces the amount of boilerplate code required, allowing developers to focus more on the logic and less on the syntax.

Parameter Handling

With MSSQL.Command.Handler, managing parameters for your SQL commands becomes a breeze. The library includes a suite of utilities designed to simplify the process of adding, modifying, and managing parameters, ensuring that your SQL commands are both dynamic and secure.

Error Management

Robust error handling mechanisms are built into the MSSQL.Command.Handler library. These mechanisms are designed to manage exceptions gracefully, ensuring that your database operations run smoothly and that any issues are logged and handled appropriately.

Asynchronous Support

The library offers full support for asynchronous operations, which is crucial for modern applications that require non-blocking database interactions. This feature allows your application to remain responsive and efficient, even during intensive database operations.

Connection Management

Efficient connection management is a cornerstone of the MSSQL.Command.Handler library. It includes built-in connection pooling and lifecycle management, which help optimize the performance and reliability of your database connections.

Result Processing

The library provides convenient methods for processing query results and converting them into usable data structures. This feature simplifies the task of working with the data retrieved from your database, making it easier to integrate with the rest of your application.

Installation

To install the MSSQL.Command.Handler package, you can use either the NuGet Package Manager or the .NET CLI. The installation process is straightforward and quick, allowing you to start using the library in your project almost immediately.

Using NuGet Package Manager

  1. Open your project in Visual Studio.
  2. Right-click on the project in Solution Explorer and select "Manage NuGet Packages."
  3. In the NuGet Package Manager, search for MSSQL.Command.Handler.
  4. Click on the MSSQL.Command.Handler package and then click the "Install" button.

Using .NET CLI

Alternatively, you can use the .NET CLI to add the package to your project. Open your command line interface and navigate to your project directory. Then, run the following command:

dotnet add package MSSQL.Command.Handler

This command will download and install the MSSQL.Command.Handler package, along with any dependencies, directly into your project.

Usage

To help you get started with MSSQL.Command.Handler, here is a basic example demonstrating how to use the library in your project:

Copy
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MSSQL.Command.Handler;

class Program
{
    static async Task Main(string[] args)
    {
        // Initialize the SqlCommandHandler with your connection string
        var commandHandler = new SqlCommandHandler("YourConnectionString");

        // Define your parameters
        var parameters = new Dictionary<string, object>
        {
            { "@Param1", "Value1" },
            { "@Param2", 123 }
        };

        // Execute a query asynchronously
        var result = await commandHandler.ExecuteQueryAsync(
            "SELECT * FROM YourTable WHERE Column1 = @Param1 AND Column2 = @Param2",
            parameters
        );

        // Process the results
        foreach (var row in result)
        {
            Console.WriteLine(row["ColumnName"]);
        }
    }
}

Explanation

Initialization: The SqlCommandHandler is initialized with a connection string that specifies the database you want to connect to. Parameter Definition: Parameters for the SQL query are defined in a dictionary, where the keys are the parameter names and the values are the parameter values. Query Execution: The ExecuteQueryAsync method is used to execute the SQL query asynchronously. This method takes the SQL query string and the parameters dictionary as arguments. Result Processing: The results of the query are processed in a loop, where each row is printed to the console.

This example demonstrates the basic usage of the MSSQL.Command.Handler library. With its comprehensive set of features and utilities, the library is designed to make database interactions as smooth and efficient as possible.

Advanced Features

Batch Operations

For applications that require the execution of multiple SQL commands in a single batch, MSSQL.Command.Handler provides robust support for batch operations. This feature allows you to group multiple commands together and execute them as a single unit, improving efficiency and performance.

Transaction Management

The library includes comprehensive support for transaction management, enabling you to execute multiple SQL commands within a single transaction. This ensures that all commands within the transaction are completed successfully or rolled back in case of an error, maintaining the integrity of your database.

Custom Data Mappers

MSSQL.Command.Handler allows you to define custom data mappers, which can be used to convert database results into custom data structures. This feature provides greater flexibility and control over how you process and use the data retrieved from your database.

Integration with ORMs

The library is designed to integrate seamlessly with popular Object-Relational Mapping (ORM) frameworks. This allows you to leverage the power of ORMs while still benefiting from the advanced features and utilities provided by MSSQL.Command.Handler.

Conclusion

The MSSQL.Command.Handler library is a powerful and versatile tool designed to simplify and enhance the process of executing and managing SQL commands in Microsoft SQL Server environments. With its comprehensive set of features, including command execution, parameter handling, error management, asynchronous support, connection management, and result processing, the library provides everything you need to interact with your databases more effectively and efficiently.

Whether you are working on a small project or a large-scale application, MSSQL.Command.Handler offers the tools and utilities you need to ensure that your database operations are smooth, reliable, and high-performing. By integrating this library into your project, you can significantly reduce the amount of boilerplate code required, simplify the management of database connections and parameters, and ensure that your application remains responsive and efficient even during intensive database operations.

Here are complete and functional examples of all components in your Windows Forms project. All required files are shown below:


Partner.cs

using System;

namespace WindowsFormsApp1
{
    public class Partner
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Director { get; set; }
        public string DirectorPhone { get; set; }
        public int Rating { get; set; }
        public string Type { get; set; }
        public string Address { get; set; }
        public string Email { get; set; }
        public int DiscountPercentage { get; set; }
        public string INN { get; set; }
    }
}

UserControl1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
	public partial class UserControl1 : UserControl
	{
		public Partner Partner { get; private set; }
		public event EventHandler<Partner> PartnerSelected;
		public event EventHandler<Partner> PartnerHistoryRequested;

		private string connectionString;
		public UserControl1(Partner partner, string connectionString)
		{
			InitializeComponent();
			this.connectionString = connectionString;
			Partner = partner;
			// Привязка данных к контролам
			nameLabel.Text = partner.Type + " | " + partner.Name;
			directorLabel.Text = $"Директор: {partner.Director}";
			phoneLabel.Text = $"+7 {partner.DirectorPhone}";
			ratingLabel.Text = $"Рейтинг: {partner.Rating}";
			partner.DiscountPercentage = CalculateDiscount(partner.Id);
			discountLabel.Text = $"{partner.DiscountPercentage}%";
			
		}
		private int CalculateDiscount(int partnerId)
		{
			decimal totalSales = GetTotalSalesByPartner(partnerId);

			if (totalSales < 10_000) return 0;
			else if (totalSales < 50_000) return 5;
			else if (totalSales < 300_000) return 10;
			else return 15;
		}

		private decimal GetTotalSalesByPartner(int partnerId)
		{
			decimal total = 0;

			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					string query = "SELECT SUM(PRODUCT_COUNT) FROM SALE WHERE PARTNER = @partnerId";
					using (var cmd = new SqlCommand(query, conn))
					{
						cmd.Parameters.AddWithValue("@partnerId", partnerId);
						object result = cmd.ExecuteScalar();
						if (result != DBNull.Value && decimal.TryParse(result.ToString(), out var value))
							total = value;
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка при расчете продаж: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}

			return total;
		}

		private void btnEdit_Click(object sender, EventArgs e)
		{
			PartnerSelected?.Invoke(this, Partner);
		}

		private void btnHistory_Click(object sender, EventArgs e)
		{
			PartnerHistoryRequested?.Invoke(this, Partner);
		}
	}
}

Form1.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private string connectionString = @"Data Source=SOUEIWINHOMEPC\SQLEXPRESS;Initial Catalog=SonyaDemo;Integrated Security=True;Encrypt=False";

        public Form1()
        {
            InitializeComponent();
            LoadPartners();
        }

        private void LoadPartners()
        {
			flowLayoutPanel1.Controls.Clear();

			string query = @"SELECT 
                    p.PARTNER_ID, 
                    p.PARTNER_NAME, 
                    p.DIRECTOR, 
                    p.DIRECTOR_PHONE, 
                    p.PARTNER_RATING, 
                    p.PARTNER_LEGAL_ADDRESS, 
                    p.DIRECTOR_MAIL, 
                    p.PARTNER_INN, 
                    pt.PARTNER_TYPE_NAME
                 FROM PARTNER p
                 JOIN PARTNER_TYPE pt ON p.PARTNER_TYPE = pt.PARTNER_TYPE_ID";

			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					using (var cmd = new SqlCommand(query, conn))
					{
						using (var reader = cmd.ExecuteReader())
						{
							while (reader.Read())
							{
								var partner = new Partner
								{
									Id = Convert.ToInt32(reader["PARTNER_ID"]),
									Name = reader["PARTNER_NAME"].ToString(),
									Director = reader["DIRECTOR"].ToString(),
									DirectorPhone = reader["DIRECTOR_PHONE"].ToString(),
									Rating = Convert.ToInt32(reader["PARTNER_RATING"]),
									Address = reader["PARTNER_LEGAL_ADDRESS"].ToString(),
									Email = reader["DIRECTOR_MAIL"].ToString(),
									INN = reader["PARTNER_INN"].ToString(),
									Type = reader["PARTNER_TYPE_NAME"].ToString()
								};

								var card = new UserControl1(partner, connectionString);
								card.PartnerSelected += (sender, p) =>
								{
									var form = new Form2(connectionString, p);
									if (form.ShowDialog() == DialogResult.OK)
										LoadPartners();
								};
								card.PartnerHistoryRequested += (sender, p) =>
								{
									var historyForm = new Form3(connectionString, p.Id, p.Name);
									historyForm.Show();
									
								};

								flowLayoutPanel1.Controls.Add(card);
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("Ошибка загрузки данных: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}


        
		private void btnAdd_Click(object sender, EventArgs e)
		{
			var form = new Form2(connectionString);
			if (form.ShowDialog() == DialogResult.OK)
				LoadPartners();
		}

		private void btnCalculateMaterial_Click(object sender, EventArgs e)
		{
			var calcForm = new Form4();
			calcForm.Show();
		}
	}
}

Form2.cs (Create/Edit Partner)

using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Linq;

namespace WindowsFormsApp1
{
    public partial class Form2 : Form
    {
        private string connectionString;
        private Partner currentPartner;
        private bool isEditMode = false;

        public Form2(string connString, Partner partner = null)
        {
			InitializeComponent();
			connectionString = connString;
			currentPartner = partner;
			isEditMode = partner != null;
			LoadPartnerTypes();
			LoadData();
		}
		private void LoadData()
		{
			if (currentPartner != null)
			{
				tbName.Text = currentPartner.Name;
				tbDirector.Text = currentPartner.Director;
				tbPhone.Text = currentPartner.DirectorPhone;
				tbMail.Text = currentPartner.Email;
				tbAddress.Text = currentPartner.Address;
				tbRating.Text = currentPartner.Rating.ToString();
				tbINN.Text = currentPartner.INN;
				cmbType.SelectedItem = currentPartner.Type;
			}
		}


		private void LoadPartnerTypes()
		{
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					var cmd = new SqlCommand("SELECT PARTNER_TYPE_NAME FROM PARTNER_TYPE", conn);
					var reader = cmd.ExecuteReader();
					while (reader.Read())
						cmbType.Items.Add(reader["PARTNER_TYPE_NAME"].ToString());
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("Ошибка загрузки типов: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private bool ValidateInputs()
        {
			if (string.IsNullOrWhiteSpace(tbName.Text))
			{
				MessageBox.Show("Введите наименование.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return false;
			}
			if (cmbType.SelectedItem == null)
			{
				MessageBox.Show("Выберите тип партнера.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return false;
			}
			if (!int.TryParse(tbRating.Text, out int rating) || rating < 0)
			{
				MessageBox.Show("Рейтинг должен быть неотрицательным числом.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return false;
			}
			return true;
		}

		private void btnCancel_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void btnSave_Click(object sender, EventArgs e)
		{
			if (!ValidateInputs()) return;

			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					string query;
					SqlCommand cmd;
					if (isEditMode)
					{
						query = @"UPDATE PARTNER SET 
                PARTNER_NAME = @name, 
                DIRECTOR = @director, 
                DIRECTOR_PHONE = @phone, 
                PARTNER_RATING = @rating, 
                PARTNER_TYPE = (SELECT PARTNER_TYPE_ID FROM PARTNER_TYPE WHERE PARTNER_TYPE_NAME = @type),
                PARTNER_LEGAL_ADDRESS = @address, 
                DIRECTOR_MAIL = @email,
                PARTNER_INN = @inn
              WHERE PARTNER_ID = @id";
						cmd = new SqlCommand(query, conn);
						cmd.Parameters.AddWithValue("@id", currentPartner.Id);
					}
					else
					{
						query = @"INSERT INTO PARTNER 
                (PARTNER_NAME, DIRECTOR, DIRECTOR_PHONE, PARTNER_RATING,
                 PARTNER_TYPE, PARTNER_LEGAL_ADDRESS, DIRECTOR_MAIL, PARTNER_INN)
              VALUES 
                (@name, @director, @phone, @rating,
                 (SELECT PARTNER_TYPE_ID FROM PARTNER_TYPE WHERE PARTNER_TYPE_NAME = @type),
                 @address, @email, @inn)";
						cmd = new SqlCommand(query, conn);
					}

					cmd.Parameters.AddWithValue("@name", tbName.Text);
					cmd.Parameters.AddWithValue("@director", tbDirector.Text);
					cmd.Parameters.AddWithValue("@phone", tbPhone.Text);
					cmd.Parameters.AddWithValue("@rating", int.Parse(tbRating.Text));
					cmd.Parameters.AddWithValue("@type", cmbType.SelectedItem.ToString());
					cmd.Parameters.AddWithValue("@address", tbAddress.Text);
					cmd.Parameters.AddWithValue("@email", tbMail.Text);
					cmd.Parameters.AddWithValue("@inn", tbINN.Text);

					cmd.ExecuteNonQuery();
					DialogResult = DialogResult.OK;
					Close();
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("Ошибка сохранения: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
	}
}

Form3.cs (Sales History)

using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form3 : Form
    {
        private string connectionString;
        private int partnerId;
		private string partnerName;
		public Form3(string connString, int partnerId, string partnerName)
        {
			InitializeComponent();
			this.connectionString = connString;
			this.partnerId = partnerId;
			this.partnerName = partnerName;
			label2.Text = $"{partnerName}";
			Load += (s, e) => LoadSalesHistory();
		}
        private void LoadSalesHistory()
        {
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();

					string query = @"
                        SELECT 
                            p.PRODUCT_NAME AS [Наименование продукции],
                            s.PRODUCT_COUNT AS [Количество],
                            s.SALE_DATE AS [Дата продажи]
                        FROM SALE s
                        JOIN PRODUCT p ON s.PRODUCT_ARTICLE = p.PRODUCT_ARTICLE
                        WHERE s.PARTNER = @partnerId";

					using (var cmd = new SqlCommand(query, conn))
					{
						cmd.Parameters.AddWithValue("@partnerId", partnerId);

						using (var adapter = new SqlDataAdapter(cmd))
						{
							var table = new DataTable();
							adapter.Fill(table);
							dataGridView1.DataSource = table;
						}
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("Ошибка загрузки истории: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

    }
}

Form4.cs (Material Calculation)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
	public partial class Form4 : Form
	{
        private static string connectionString = @"Data Source=SOUEIWINHOMEPC\SQLEXPRESS;Initial Catalog=SonyaDemo;Integrated Security=True;Encrypt=False";

		public Form4()
		{
			InitializeComponent();
			LoadProductTypes();
			LoadMaterialTypes();
		}
		private void LoadProductTypes()
		{
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					var cmd = new SqlCommand("SELECT PRODUCT_TYPE_ID, PRODUCT_TYPE_NAME FROM PRODUCT_TYPE", conn);
					var reader = cmd.ExecuteReader();
					while (reader.Read())
					{
						cmbProductType.Items.Add(new ProductTypeInfo
						{
							Id = Convert.ToInt32(reader["PRODUCT_TYPE_ID"]),
							Name = reader["PRODUCT_TYPE_NAME"].ToString()
						});
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка загрузки типов продукции: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private void LoadMaterialTypes()
		{
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					var cmd = new SqlCommand("SELECT MATERIAL_TYPE_ID, MATERIAL_TYPE_NAME FROM MATERIAL_TYPE", conn);
					var reader = cmd.ExecuteReader();
					while (reader.Read())
					{
						cmbMaterialType.Items.Add(new MaterialTypeInfo
						{
							Id = Convert.ToInt32(reader["MATERIAL_TYPE_ID"]),
							Name = reader["MATERIAL_TYPE_NAME"].ToString()
						});
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка загрузки типов материалов: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void btnCalculate_Click(object sender, EventArgs e)
		{
			try
			{
				if (cmbProductType.SelectedItem == null || cmbMaterialType.SelectedItem == null ||
					!int.TryParse(tbProductCount.Text, out int productCount) ||
					!decimal.TryParse(tbParam1.Text, out decimal param1) ||
					!decimal.TryParse(tbParam2.Text, out decimal param2))
				{
					MessageBox.Show("Введите корректные данные.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					return;
				}

				var productType = (ProductTypeInfo)cmbProductType.SelectedItem;
				var materialType = (MaterialTypeInfo)cmbMaterialType.SelectedItem;

				int result = CalculateMaterial(productType.Id, materialType.Id, productCount, param1, param2);

				if (result == -1)
				{
					MessageBox.Show("Некорректные данные или типы.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
				}
				else
				{
					lblResult.Text = $"{result} шт.";
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка расчета: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		public static int CalculateMaterial(int productTypeId, int materialTypeId, int productCount, decimal param1, decimal param2)
		{
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();

					// Получаем коэффициент типа продукции
					string queryCoeff = "SELECT PRODUCT_TYPE_COEFFICIENT FROM PRODUCT_TYPE WHERE PRODUCT_TYPE_ID = @id";
					var cmdCoeff = new SqlCommand(queryCoeff, conn);
					cmdCoeff.Parameters.AddWithValue("@id", productTypeId);
					var resultCoeff = cmdCoeff.ExecuteScalar();
					if (resultCoeff == null || !(resultCoeff is decimal coeff))
						return -1;

					// Получаем процент брака материала
					string queryDefect = "SELECT PERCENTAGE_DEFECTIVE_MATERIAL FROM MATERIAL_TYPE WHERE MATERIAL_TYPE_ID = @id";
					var cmdDefect = new SqlCommand(queryDefect, conn);
					cmdDefect.Parameters.AddWithValue("@id", materialTypeId);
					var resultDefect = cmdDefect.ExecuteScalar();
					if (resultDefect == null || !(resultDefect is decimal defect))
						return -1;

					// Проверка положительности параметров
					if (param1 <= 0 || param2 <= 0 || productCount <= 0)
						return -1;

					// Расчет
					decimal baseMaterial = param1 * param2 * coeff * productCount;
					decimal materialWithDefect = baseMaterial * (1 + defect);
					return (int)Math.Ceiling(materialWithDefect);
				}
			}
			catch
			{
				return -1;
			}
		}
		public class ProductTypeInfo
		{
			public int Id { get; set; }
			public string Name { get; set; }
			public override string ToString() => Name;
		}

		public class MaterialTypeInfo
		{
			public int Id { get; set; }
			public string Name { get; set; }
			public override string ToString() => Name;
		}
	}
}



Example second code example

Partner

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace probaDemo.SOURCES
{
	public class Partner
	{
		public int Id { get; set; }
		public string Name { get; set; }
		public string Director { get; set; }
		public string DirectorPhone { get; set; }
		public int Rating { get; set; }
		public string Type { get; set; }
		public string Address { get; set; }
		public string Email { get; set; }
		public int DiscountPercentage { get; set; }
		public string INN { get; set; }
	}
}

Partner Control

using probaDemo.SOURCES;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace probaDemo.GUI
{
	public partial class PartnerControl : UserControl
	{
		public Partner Partner { get; private set; }
		public event EventHandler<Partner> PartnerSelected;
		public event EventHandler<Partner> PartnerHistoryRequested;

		private string connectionString;

		public PartnerControl(Partner partner, string connectionString)
		{
			InitializeComponent();
			this.connectionString = connectionString;
			Partner = partner;
			// Привязка данных к контролам
			label1.Text = partner.Type;
			label2.Text = partner.Name;
			label3.Text = $"Директор: {partner.Director}";
			label4.Text = $"+7 {partner.DirectorPhone}";
			label5.Text = $"Рейтинг: {partner.Rating}";
			partner.DiscountPercentage = CalculateDiscount(partner.Id);
			label6.Text = $"{partner.DiscountPercentage}%";

		}
		private int CalculateDiscount(int partnerId)
		{
			decimal totalSales = GetTotalSalesByPartner(partnerId);

			if (totalSales < 10_000) return 0;
			else if (totalSales < 50_000) return 5;
			else if (totalSales < 300_000) return 10;
			else return 15;
		}

		private decimal GetTotalSalesByPartner(int partnerId)
		{
			decimal total = 0;

			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					string query = "SELECT SUM(PRODUCT_COUNT) FROM SALE WHERE PARTNER = @partnerId";
					using (var cmd = new SqlCommand(query, conn))
					{
						cmd.Parameters.AddWithValue("@partnerId", partnerId);
						object result = cmd.ExecuteScalar();
						if (result != DBNull.Value && decimal.TryParse(result.ToString(), out var value))
							total = value;
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка при расчете продаж: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}

			return total;
		}

		private void guna2Button2_Click(object sender, EventArgs e)
		{

			PartnerSelected?.Invoke(this, Partner);
		}

		private void guna2Button1_Click(object sender, EventArgs e)
		{
			PartnerHistoryRequested?.Invoke(this, Partner);
			
		}

	}
}

MainForm

using probaDemo.GUI;
using probaDemo.SOURCES;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace probaDemo
{
	public partial class MainForm : Form
	{
		//private string connectionString = @"Data Source=WIN-VS55Q9L8V14;Initial Catalog=demo;Integrated Security=True;Encrypt=False";

        private static string connectionString = @"Data Source=WIN-VS55Q9L8V14;Initial Catalog=demo;Integrated Security=True;Encrypt=False";

        public MainForm()
		{
			InitializeComponent();
			LoadPartners();
			LoadProductTypes();
			LoadMaterialTypes();
		}
		private void LoadPartners()
		{
			flowLayoutPanel1.Controls.Clear();

			string query = @"SELECT   PARTNER.PARTNER_ID,  PARTNER.PARTNER_NAME, PARTNER.DIRECTOR, PARTNER.DIRECTOR_MAIL, PARTNER.DIRECTOR_PHONE, PARTNER.PARTNER_LEGAL_ADDRESS, PARTNER.PARTNER_INN, PARTNER.PARTNER_RATING, PARTNER.PARTNER_TYPE, PARTNER_TYPE.PARTNER_TYPE_ID, 
                  PARTNER_TYPE.PARTNER_TYPE_NAME
				  FROM        PARTNER INNER JOIN
                  PARTNER_TYPE ON PARTNER.PARTNER_TYPE = PARTNER_TYPE.PARTNER_TYPE_ID";
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					using (var cmd = new SqlCommand(query, conn))
					{
						using (var reader = cmd.ExecuteReader())
						{
							while (reader.Read())
							{
								var partner = new Partner
								{
									Id = Convert.ToInt32(reader["PARTNER_ID"]),
									Name = reader["PARTNER_NAME"].ToString(),
									Director = reader["DIRECTOR"].ToString(),
									DirectorPhone = reader["DIRECTOR_PHONE"].ToString(),
									Rating = Convert.ToInt32(reader["PARTNER_RATING"]),
									Address = reader["PARTNER_LEGAL_ADDRESS"].ToString(),
									Email = reader["DIRECTOR_MAIL"].ToString(),
									INN = reader["PARTNER_INN"].ToString(),
									Type = reader["PARTNER_TYPE_NAME"].ToString()
								};
								var card = new PartnerControl(partner, connectionString);
								card.PartnerSelected += (IChannelSender, p) =>
								{
									var partnerDetailsForm = new PartnerDetailsForm(connectionString, p);
									if (partnerDetailsForm.ShowDialog() == DialogResult.OK)
									{
										LoadPartners();
									}
								};
								card.PartnerHistoryRequested += (sender, p) =>
								{
									var historyForm = new PartnerHistoryForm(connectionString, p.Id);
									historyForm.ShowDialog();
								};
								flowLayoutPanel1.Controls.Add(card);
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка при загрузке партнеров: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void guna2Button1_Click(object sender, EventArgs e)
		{
			var form = new PartnerDetailsForm(connectionString);
			if (form.ShowDialog() == DialogResult.OK)
				LoadPartners();
		}

		private void guna2Button2_Click(object sender, EventArgs e)
		{
			//var calcForm = new Form4();
			//calcForm.Show();
		}

		private void label1_Click(object sender, EventArgs e)
		{

		}

        private void guna2TabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            LoadPartners();
        }

        private void guna2TabControl1_TabIndexChanged(object sender, EventArgs e)
        {
            LoadPartners();
        }

        private void pARTNERBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.pARTNERBindingSource.EndEdit();
            this.tableAdapterManager.UpdateAll(this.demoDataSet);
			LoadPartners();

        }

        private void MainForm_Load(object sender, EventArgs e)
        {
			// TODO: данная строка кода позволяет загрузить данные в таблицу "demoDataSet.PARTNER". При необходимости она может быть перемещена или удалена.
			this.pARTNERTableAdapter.Fill(this.demoDataSet.PARTNER);
			

        }

		private void guna2Button2_Click_1(object sender, EventArgs e)
		{
			try
			{
				if (comboBox1.SelectedItem == null || comboBox2.SelectedItem == null ||
					!int.TryParse(textBox1.Text, out int productCount) ||
					!decimal.TryParse(textBox2.Text, out decimal param1) ||
					!decimal.TryParse(textBox3.Text, out decimal param2))
				{
					MessageBox.Show("Введите корректные данные.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					return;
				}

				var productType = (ProductTypeInfo)comboBox1.SelectedItem;
				var materialType = (MaterialTypeInfo)comboBox2.SelectedItem;

				int result = CalculateMaterial(productType.Id, materialType.Id, productCount, param1, param2);

				if (result == -1)
				{
					MessageBox.Show("Некорректные данные или типы.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
				}
				else
				{
					label7.Text = $"{result} шт.";
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка расчета: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private void LoadProductTypes()
		{
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					var cmd = new SqlCommand("SELECT PRODUCT_TYPE_ID, PRODUCT_TYPE_NAME FROM PRODUCT_TYPE", conn);
					var reader = cmd.ExecuteReader();
					while (reader.Read())
					{
						comboBox1.Items.Add(new ProductTypeInfo
						{
							Id = Convert.ToInt32(reader["PRODUCT_TYPE_ID"]),
							Name = reader["PRODUCT_TYPE_NAME"].ToString()
						});
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка загрузки типов продукции: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private void LoadMaterialTypes()
		{
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					var cmd = new SqlCommand("SELECT MATERIAL_TYPE_ID, MATERIAL_TYPE_NAME FROM MATERIAL_TYPE", conn);
					var reader = cmd.ExecuteReader();
					while (reader.Read())
					{
						comboBox2.Items.Add(new MaterialTypeInfo
						{
							Id = Convert.ToInt32(reader["MATERIAL_TYPE_ID"]),
							Name = reader["MATERIAL_TYPE_NAME"].ToString()
						});
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show($"Ошибка загрузки типов материалов: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		public static int CalculateMaterial(int productTypeId, int materialTypeId, int productCount, decimal param1, decimal param2)
		{
			try
			{ 
			using (var conn = new SqlConnection(connectionString))
			{
				conn.Open();

				// Получаем коэффициент типа продукции
				string queryCoeff = "SELECT PRODUCT_TYPE_COEFFICIENT FROM PRODUCT_TYPE WHERE PRODUCT_TYPE_ID = @id";
				var cmdCoeff = new SqlCommand(queryCoeff, conn);
				cmdCoeff.Parameters.AddWithValue("@id", productTypeId);
				var resultCoeff = cmdCoeff.ExecuteScalar();
				if (resultCoeff == null || !(resultCoeff is decimal coeff))
					return -1;

				// Получаем процент брака материала
				string queryDefect = "SELECT PERCENTAGE_DEFECTIVE_MATERIAL FROM MATERIAL_TYPE WHERE MATERIAL_TYPE_ID = @id";
				var cmdDefect = new SqlCommand(queryDefect, conn);
				cmdDefect.Parameters.AddWithValue("@id", materialTypeId);
				var resultDefect = cmdDefect.ExecuteScalar();
				if (resultDefect == null || !(resultDefect is decimal defect))
					return -1;

				// Проверка положительности параметров
				if (param1 <= 0 || param2 <= 0 || productCount <= 0)
					return -1;

				// Расчет
				decimal baseMaterial = param1 * param2 * coeff * productCount;
				decimal materialWithDefect = baseMaterial * (1 + defect);
				return (int)Math.Ceiling(materialWithDefect);
			}
			}
			catch
			{
				return -1;
			}
		}
		public class ProductTypeInfo
		{
			public int Id { get; set; }
			public string Name { get; set; }
			public override string ToString() => Name;
		}
		public class MaterialTypeInfo
		{
			public int Id { get; set; }
			public string Name { get; set; }
			public override string ToString() => Name;
		}

	}
}

PartnerDetailsForm

using probaDemo.SOURCES;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;

namespace probaDemo.GUI
{
    public partial class PartnerDetailsForm : Form
    {
        private string connectionString;
        private Partner currentPartner;
        private bool isEditMode = false;
        public PartnerDetailsForm(string connString, Partner partner = null)
        {
            InitializeComponent();
            connectionString = connString;
            currentPartner = partner;
            isEditMode = partner != null;
			LoadPartnerTypes();
			LoadData();
		}
		private void LoadData()
		{
			if (currentPartner != null)
			{
				pARTNER_NAMETextBox.Text = currentPartner.Name;
				dIRECTORTextBox.Text = currentPartner.Director;
				dIRECTOR_PHONETextBox.Text = currentPartner.DirectorPhone;
				dIRECTOR_MAILTextBox.Text = currentPartner.Email;
				pARTNER_LEGAL_ADDRESSTextBox.Text = currentPartner.Address;
				pARTNER_RATINGTextBox.Text = currentPartner.Rating.ToString();
				pARTNER_INNTextBox.Text = currentPartner.INN;
				comboBox1.SelectedItem = currentPartner.Type;
			}
		}

		private void LoadPartnerTypes()
        {
            try
            {
                using (var conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    var cmd = new SqlCommand("SELECT PARTNER_TYPE_NAME FROM PARTNER_TYPE", conn);
                    var reader = cmd.ExecuteReader();
                    while (reader.Read())
                        comboBox1.Items.Add(reader["PARTNER_TYPE_NAME"].ToString());
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ошибка загрузки типов: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
		private bool ValidateInputs()
		{
			if (string.IsNullOrWhiteSpace(pARTNER_NAMETextBox.Text))
			{
				MessageBox.Show("Введите наименование.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return false;
			}
			if (comboBox1.SelectedItem == null)
			{
				MessageBox.Show("Выберите тип партнера.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return false;
			}
			if (!int.TryParse(pARTNER_RATINGTextBox.Text, out int rating) || rating < 0)
			{
				MessageBox.Show("Рейтинг должен быть неотрицательным числом.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return false;
			}
			return true;
		}


      

        

        private void guna2Button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }



        private void pARTNERBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
			if (!ValidateInputs()) return;

			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();
					string query;
					SqlCommand cmd;
					if (isEditMode)
					{
						query = @"UPDATE PARTNER SET 
                PARTNER_NAME = @name, 
                DIRECTOR = @director, 
                DIRECTOR_PHONE = @phone, 
                PARTNER_RATING = @rating, 
                PARTNER_TYPE = (SELECT PARTNER_TYPE_ID FROM PARTNER_TYPE WHERE PARTNER_TYPE_NAME = @type),
                PARTNER_LEGAL_ADDRESS = @address, 
                DIRECTOR_MAIL = @email,
                PARTNER_INN = @inn
              WHERE PARTNER_ID = @id";
						cmd = new SqlCommand(query, conn);
						cmd.Parameters.AddWithValue("@id", currentPartner.Id);
					}
					else
					{
						query = @"INSERT INTO PARTNER 
                (PARTNER_NAME, DIRECTOR, DIRECTOR_PHONE, PARTNER_RATING,
                 PARTNER_TYPE, PARTNER_LEGAL_ADDRESS, DIRECTOR_MAIL, PARTNER_INN)
              VALUES 
                (@name, @director, @phone, @rating,
                 (SELECT PARTNER_TYPE_ID FROM PARTNER_TYPE WHERE PARTNER_TYPE_NAME = @type),
                 @address, @email, @inn)";
						cmd = new SqlCommand(query, conn);
					}

					cmd.Parameters.AddWithValue("@name", pARTNER_NAMETextBox.Text);
					cmd.Parameters.AddWithValue("@director", dIRECTORTextBox.Text);
					cmd.Parameters.AddWithValue("@phone", dIRECTOR_PHONETextBox.Text);
					cmd.Parameters.AddWithValue("@rating", int.Parse(pARTNER_RATINGTextBox.Text));
					cmd.Parameters.AddWithValue("@type", comboBox1.SelectedItem.ToString());
					cmd.Parameters.AddWithValue("@address", pARTNER_LEGAL_ADDRESSTextBox.Text);
					cmd.Parameters.AddWithValue("@email", dIRECTOR_MAILTextBox.Text);
					cmd.Parameters.AddWithValue("@inn", pARTNER_INNTextBox.Text);

					cmd.ExecuteNonQuery();
					DialogResult = DialogResult.OK;
					Close();
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("Ошибка сохранения: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void dIRECTOR_PHONETextBox_KeyPress(object sender, KeyPressEventArgs e)
		{
			// Разрешаем только цифры и клавишу Backspace
			if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
			{
				e.Handled = true; // Блокируем ввод
			}
		}
	}
}

PartnerHistoryForm

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace probaDemo.GUI
{
	public partial class PartnerHistoryForm : Form
	{
		private string connectionString;
		private int partnerId;
		private string partnerName;
		public PartnerHistoryForm(string connString, int partnerId)
		{
			InitializeComponent();
			this.connectionString = connString;
			this.partnerId = partnerId;
			this.partnerName = partnerName;
			Load += (s, e) => LoadSalesHistory();
		}
		private void LoadSalesHistory()
		{
			try
			{
				using (var conn = new SqlConnection(connectionString))
				{
					conn.Open();

					string query = @"
                        SELECT 
                            p.PRODUCT_NAME AS [Наименование продукции],
                            s.PRODUCT_COUNT AS [Количество],
                            s.SALE_DATE AS [Дата продажи]
                        FROM SALE s
                        JOIN PRODUCT p ON s.PRODUCT_ARTICLE = p.PRODUCT_ARTICLE
                        WHERE s.PARTNER = @partnerId";

					using (var cmd = new SqlCommand(query, conn))
					{
						cmd.Parameters.AddWithValue("@partnerId", partnerId);

						using (var adapter = new SqlDataAdapter(cmd))
						{
							var table = new DataTable();
							adapter.Fill(table);
							guna2DataGridView1.DataSource = table;
						}
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("Ошибка загрузки истории: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private void guna2Button1_Click(object sender, EventArgs e)
		{
			Close();
		}
	}
}
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net7.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.4.6 197 6/17/2025
1.4.5 175 6/15/2025
1.4.3 264 6/13/2025
1.4.2 264 6/13/2025